2013-10-24 36 views
7

我在創建模擬響應對象以與我的單元測試一起使用時遇到問題。我正在使用org.glassfish.jersey.core.jersey-client版本2.3.1來實現我的RESTful客戶端和mockito版本1.9.5以幫助我處理模擬對象。這是我的測試代碼:無法模擬Glassfish Jersey客戶端響應對象

@Test 
public void testGetAll() throws IOException { 
    // Given 
    String expectedResource = "expectedResource" 

    final Response expectedRes = Response.ok(expectedResource, MediaType.APPLICATION_JSON).build(); 
    String receivedResource; 

    BDDMockito.given(this.client.getSimpleClient().getAllWithResponse()).willReturn(expectedRes); 

    // When 
    receivedResource = this.client.getAll(); 

    // Then 
    Assert.assertNotNull("Request constructed correctly and response received.", receivedResource); 
    Assert.assertEquals("Resource is equal to expected.", expectedResource, receivedResource); 
} 

執行this.client.getAll();時會出現此問題。下面是該方法的代碼:

public String getAll() throws GenericAragornException, ProcessingException{ 
    Response response = this.simpleClient.getAllWithResponse(); 

    if (response.getStatus() != 200) { 
     processErrorResponse(response); 
    } 

    String entity = response.readEntity(String.class); 

    // No errors so return entity converted to resourceType. 
    return entity; 
} 

注意,我用嘲笑的手動創建響應this.simpleClient.getAllWithResponse()方法。當它到達response.readEntity(resourceListType);指令時,Jersey會拋出以下異常:java.lang.IllegalStateException - Method not supported on an outbound message.。經過大量研究和調試後,出於某種原因,當我使用響應構建器(如Response.ok(expectedResource, MediaType.APPLICATION_JSON).build();)創建響應時,它會將其創建爲OutboundResponse,而不是將其創建爲InboundResponse。後者是唯一允許使用Response.readEntity()方法的人。如果它是OutboundResponse,則引發異常。

但是,我找不到任何方法將手動創建的響應轉換爲InboundResponse。所以我的測試是註定的:(你們/ gals對我在這裏可以做什麼有所瞭解嗎?我不想用Mockito來模擬Response對象,因爲我認爲它可能是代碼異味,因爲它違反了得墨忒耳,真誠的,我的想法在這裏。像這樣的事情應該是簡單明瞭。

回答

5

,因爲當你使用ResponseBuilder,它返回一個OutboundJaxrsResponse消息不能readEntity()處理我有這個錯誤。

我注意到只有當我直接調用Jax-RS組件時纔有這個錯誤,例如,如果我有DefaultController註釋了@Path("/default"),並且如果我試圖直接調用它的方法,我就不能使用readEntity()和你有同樣的錯誤。

defaultController.get(); 

現在,當我用的是grizzly2測試提供商和使用客戶端定位的REST URL(在之前的情況下,它是/default),我在響應接收到的消息是一個ScopedJaxrsResponse。然後我可以使用readEntity()方法。

target("/default").request.get(); 

在你的情況,你才能與ResponseBuilder內置的響應不是由球衣處理回覆嘲笑SimpleClient的。這可以直接調用我的DefaultController方法。

如果不嘲笑readEntity()方法,我建議您找到一種方法讓您的回覆由Jersey處理並轉換爲ScopedJaxrsResponse

希望有所幫助。

+0

托馬斯,感謝您的輸入!只有一個問題......如果是你......你會嘲笑readEntity()方法嗎? –

+0

這取決於你想測試什麼? – Thomas

+0

getAll方法執行它應該執行的操作,並根據它接收的內容返回它應該返回的內容。 –

2

而不是使用readEntity(OutputClass.class)你可以這樣做:

OutputClass entity = (OutputClass)outboundJaxrsResponse.entity 
+0

不理想不得不改變源代碼,但這個伎倆。謝謝。 –

0

我解決了嘲諷的迴應:

@Spy Response response; 

... 

// for assignments in code under testing: 
doReturn(response).when(dwConnector).getResource(anyString()); 

// for entity and response status reading: 
doReturn("{a:1}".getBytes()).when(response).readEntity(byte[].class); 
doReturn(200).when(response).getStatus(); 

這些可以幫助,如果您的轉向是手動創建一個ScopedJaxrsResponse代替:

1

您還可以使用模擬的Mockito響應:

final Response response = Mockito.mock(Response.class); 
Mockito.when(response.getStatus()).thenReturn(responseStatus); 
Mockito.when(response.readEntity(Mockito.any(Class.class))).thenReturn(responseEntity); 
Mockito.when(response.readEntity(Mockito.any(GenericType.class))).thenReturn(responseEntity); 

responseStatus是與響應關聯狀態代碼和responseEnitty是要返回過程中的實體。您可以使用該模擬作爲Mockito中的返回語句(例如... thenReturn(response))。

在我的項目中,我爲不同類型的mock(在這種情況下爲Response)創建了構建器,因此我可以輕鬆地按需構建所需的mock,例如,狀態碼200和附加的一些自定義實體的響應。

2

對我來說,這些答案都不起作用,因爲我試圖編寫一個服務器端單元測試,測試生成的Response實例本身的主體。我通過調用String entity = readEntity(String.class)這樣的一行來得到這個例外。我不想嘲笑Response的對象,我想測試它。

對我來說,修復是上述問題的行替換到一個像:

String entity = (String) outboundJaxrsResponse.getEntity(); 
+0

或者'''LinkedHashMap結果=(LinkedHashMap)successResponse.getEntity();'''.. –

+0

謝謝,這比接受的響應更有幫助! –

相關問題