2012-05-09 77 views
4

我想爲我有的類編寫單元測試。這個類有一個公共方法,在公共方法裏面有對同一個類中的私有方法的調用。我想嘲笑那些私人方法的調用。該類是這樣的:嘲笑使用PowerMock,Mockito和TestNG的公共方法的私有方法

public class SomeClass { 
    public int somePublicMethod(int num) { 
     int num2 = somePrivateMethod1(num); 
     int num3 = somePrivateMethod2(num); 

     return num2 + num3; 
    } 

    private int somePrivateMethod1(int num) { 
     return 2*num; 
    } 

    private int somePrivateMethod2(int num) { 
     return 3*num; 
    } 
} 

對於我的單元測試,我試圖使用PowerMock與Mockito和TestNG。這是我在一個測試somePublicMethod測試的嘗試:

import static org.powermock.api.mockito.PowerMockito.doReturn; 
import static org.powermock.api.mockito.PowerMockito.spy; 

import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.testng.Assert; 
import org.testng.annotations.Test; 

@PrepareForTest(SomeClass.class) 
public class SomeClassTest { 

    @Test 
    public void testSomePublicMethod() throws Exception { 
     int num = 4;   

     SomeClass someClassSpy = spy(new SomeClass()); 

     doReturn(8).when(someClassSpy, "somePrivateMethod1", num); 
     doReturn(12).when(someClassSpy, "somePrivateMethod2", num); 

     int result = someClassSpy.somePublicMethod(num); 

     Assert.assertEquals(result, 20); 
    } 
} 

當我運行這個測試,我得到一個例外,一些提示:

FAILED: testSomePublicMethod 
org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here: 
-> at org.powermock.api.mockito.internal.PowerMockitoCore.doAnswer(PowerMockitoCore.java:31) 

E.g. thenReturn() may be missing. 
Examples of correct stubbing: 
    when(mock.isOk()).thenReturn(true); 
    when(mock.isOk()).thenThrow(exception); 
    doThrow(exception).when(mock).someVoidMethod(); 
Hints: 
1. missing thenReturn() 
2. you are trying to stub a final method, you naughty developer! 

我看了一些在線的例子,但我的天堂」發現一個使用PowerMock與Mockito和TestNG專門做我想做的事情。有人能給我一些關於我可以做什麼不同的指示嗎?

回答

0

我認爲你在這裏是一個Mockito限制。在類似情況下,我使用Powermock方法替換,或者將目標方法聲明爲protected,並在構造測試類實例時覆蓋它。 希望有所幫助。

1

你不能這樣做。你有沒有嘗試使用反射?通過使用反射,您可以通過模擬調用方法來模擬私有方法,或者更簡單:您可以將其更改爲公共臨時,然後在測試之後(可能在tearDown中) - 您可以將其更改爲私有方法。

希望得到這個幫助。

5

我不認爲這是PowerMock的問題。它看起來應該很好地工作。我不知道TestNG與PowerMock交互是否存在問題?

我對TestNG沒有經驗,所以我試着在JUnit中運行這個類。 SomeClass留下按原樣SomeClassTest最低限度地修改以使用JUnit:

import static org.powermock.api.mockito.PowerMockito.*; 

import org.junit.Assert; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest(SomeClass.class) 
public class SomeClassTest { 

    @Test 
    public void testSomePublicMethod() throws Exception { 
     final int num = 4; 

     final SomeClass someClassSpy = spy(new SomeClass()); 

     doReturn(8).when(someClassSpy, "somePrivateMethod1", num); 
     doReturn(12).when(someClassSpy, "somePrivateMethod2", num); 

     final int result = someClassSpy.somePublicMethod(num); 

     Assert.assertEquals(result, 20); 
    } 
} 

,則測試通過。

您是否需要使用@RunWIth或類似的註釋來指定PowerMockRunner.class,就像使用JUnit一樣?如果我刪除該註釋,我會收到您發佈的相同錯誤消息。

編輯:

根據此鏈接: http://code.google.com/p/powermock/wiki/TestNG_usage

你需要告訴TestNG的使用PowerMock對象工廠。要以編程方式做到這一點,這樣的方法添加到您的測試類:

@ObjectFactory 
public IObjectFactory getObjectFactory() { 
    return new org.powermock.modules.testng.PowerMockObjectFactory(); 
} 

,或者是在安全起見,你也可以從PowerMockTestCase擴展:

@PrepareForTest(SomeClass.class) 
public class SomeClassTest extends PowerMockTestCase { 
    //... 
}