2015-03-18 96 views
0

我有一個單元測試失敗,因爲它間接調用了一個依賴於服務的方法。但是,當單元測試運行時,服務處於脫機狀態。我試圖用Mockito來嘲笑這個服務依賴方法的行爲,但問題是這個方法是最終類中的靜態方法,所以在這種情況下Mockito不起作用。單元測試失敗,因爲服務處於脫機狀態

我也嘗試過使用PowerMock與Mockito,但由於該方法不是直接從單元測試中調用,所以不起作用。這是我的單元測試的骨架:

@RunWith(PowerMockRunner.class) 
@PrepareForTest(FinalClassWithStaticMethod.class) 
public class MyObjTestCase { 
    @Test public void myRandomTest() throws Exception { 
     PowerMockito.mockStatic(FinalClassWithStaticMethod.class); 
     MyObj returnObj = new MyObj(); 
     // setup fields for returnObj 
     ... 
     ... 
     PowerMockito.when(FinalClassWithStaticMethod.staticMethod((AnotherObj)anyObject())).thenReturn(returnObj); 
     AnotherObj obj = new AnotherObj(); 
     // setup fields for obj... 

     MyObj mockedObj =  FinalClassWithStaticMethod.staticMethod(obj); // This returns the mocked value. 
     // TestUtil.staticMethod calls another class' method which calls FinalClassWithStaticMethod.staticMethod. 
     MyObj myObj = TestUtil.staticMethod(obj); // This does not return mocked value. 
    } 
} 

我的問題:

甚至意味着這些場景的單元測試?

有沒有辦法讓我的單元測試在沒有修改最終課程的情況下工作?如果我不得不修改現有類,那麼對相關代碼的影響最小的正確方法是什麼?雖然這是一個特定的場景,但是鏈接到展示這種重構的例子將會很有幫助。

回答

0

就你而言,你最好是嘲笑服務對象。只有在調用服務的方法使用模擬對象時,模擬纔會起作用。如果在單元測試中創建對象時,可以創建服務的客戶端並將其傳遞給直接從單元測試(setter/constructor)調用服務的類,則不必進行太多更改。

示例代碼:

class CallsService { 
    public CallsService(final ServiceClient client) { 
    ... } 
    public someMethod() { 
     client.callService(); 
    } 
} 

在單元測試:

void test() { 
    ServiceClient mockedClient = mock(ServiceClient.class); 
    // Setup mocks to return as required 
    CallsService caller = new CallsService(mockedClient); 
} 

這樣主叫方將使用mockedClient在單元測試,並在實際的程序就可以得到一個客戶端到真正的服務。