2012-03-23 136 views
3

我有問題,我喜歡測試一些在我的junit測試中被另一種方法隱藏的值。你會如何處理這樣的事情。用Mockito?子類?如何在testet方法中用斷言編寫單元測試?

問題就在這裏:

public class MyService extends AbstractService { 

public ResponseObject insert(SomeData data) { 
    Request request = createRequest(data); 
    Response response = new Response(); 
    callService(request, response); 
    return createResponseObject(response); 
} 

protected void callBackendService(...) { 
    ... 
} 
} 

你會如何測試傳遞給

callBackendService()
方法的價值?

有比使用子類更優雅的方法嗎?

MyService service = new MyService() { 

    @Override 
    protected void callBackendService(...) { 
     assertEquals(...); 
     ... 
    } 
} 

問候,

邁克

+2

測試'callService'。製作一個「響應」,調用該方法並進行測試。 – khachik 2012-03-23 13:30:42

+1

是callService()應該是callBackendService()? – Sean 2012-03-23 13:40:16

回答

1

不要測試callBackendService(),如果它只是一個實現細節。如果它非常複雜,應該進行自己的測試,請將其重構爲一個單獨的課程。

2

一派思想是,你應該只測試你的公開課。因此,只需要對從insert()返回的ResponseObject做出斷言。否則,使用像Mockito這樣的模擬框架,可以將callBackendService()方法分解到它自己的類中(例如ServiceCaller)。然後,您可以創建一個模擬的ServiceCaller對象,並將其傳遞給它的參數創建爲。

事情是這樣的......

public class ServiceCaller { 

    public callBackendService(Request request, Response response) { 
     ... 
    } 

} 

那麼你的類應該是這個樣子......

public class MyService extends AbstractService { 


    private ServiceCaller serviceCaller; 

    public ResponseObject insert(SomeData data) { 
    Request request = createRequest(data); 
    Response response = new Response(); 
    serviceCaller.callBackendService(request, response); 
    return createResponseObject(response); 
    } 

    public setServiceCaller(ServiceCaller caller) { 
     this.serviceCaller = caller;   
    } 

} 

最後一個測試的Mockito是這樣的財產以後...

@Test 
public void testInsert() throws Exception { 

    // object to test 
    MyService ms = new MyService(); 

    // test input values 
    Request req = new Request(); 

    Response resp = new Response(); 

    // create a mock class and inject it into your test class 
    ServiceCaller sc = mock(ServiceCaller.class); 

    ms.setServiceCaller = sc; 

    // execute the method under test 
    ms.insert(req, resp); 

    // now you can see if your mock was called with the expected params 
    verify(sc).callBackendService(req, resp); 
} 

爲了簡潔起見,我已經省略了使用Interfaces等的優秀設計,但您會明白。

1

注:我假設callService()應該callBackendService()

在自己的類之一,更注重測試行爲,而不是類的方法之間的相互作用。測試行爲(與您正在嘗試的行爲相反)會使您的測試與您的實施緊密結合。因此,例如,如果您繼續嘗試測試callBackendService()方法,並稍後更改班級的實現細節,則會破壞您的測試。相反,如果您專注於測試insert()方法的行爲,那麼您可以隨時修改該特定呼叫,並且只有在實際違反了預期行爲的情況下,您的測試纔會中斷。

此外,讓我們來看看更詳細的插入方法。如果您在其他測試中測試了createRequest()方法和new Response()構造函數的行爲,那麼您已經知道這些方法正在產生您期望的結果。因此,創建一個單獨的測試來驗證callBackendService()方法在這種情況下收到的參數實際上並不是測試任何新東西。

你應該做的是測試調用insert()方法的結果。

所以你的問題的答案是,不要測試callBackendService()方法的參數。

相關問題