2017-08-30 52 views
0

我無法涵蓋以下功能「postJson」與測試(JUnit的/的Mockito),並不能找到一種方式來嘲笑線response = getTarget(path).request().post(entity, Map.class);模擬請求/使用後的Mockito

//Constructor 
public HttpService() { 
    this.client = ClientBuilder.newClient(); 
} 

Client client; 

public Map<String, ?> postJson(String path, Map<String, ?> data){ 
    Map<String, ?> response = null; 

    try { 
     Entity<Map<String, ?>> entity = Entity.entity(data, MediaType.APPLICATION_JSON); 
     response = getTarget(path).request().post(entity, Map.class); 
    } catch (Exception e) { 
     LOG.error(e.toString()); 
    } 

    return response; 
} 

public WebTarget getTarget(String path){ 
    return client.target(BASE_URI + path); 
} 

我目前測試

@Test 
public void postJsonTest(){ 
    assertEquals(null,new HttpService().postJson("", new HashMap<String,Integer>())); 

    //Verifica se a função de comunicação com servidor é chamda 
    Map<String,String> resposta = new HashMap<String,String>(); 
    HttpService mock = spy(HttpService.class); 

    assertEquals(mock.postJson("",resposta),null); 

    Mockito.verify(mock,Mockito.atLeast(1)).postJson("", resposta); 
    Mockito.verify(mock,Mockito.atLeast(1)).getTarget(Mockito.anyString()); 
} 

我找不到在'request()'之後的測試代碼。任何人都可以給我一個例子/解釋我可以如何使用mockito來覆蓋這個函數?

+0

增加在後,客戶端是在類的屬性 –

+0

客戶端已經在實例化類 –

+0

你的問題的構造是在構造函數中的靜態方法調用。你可能想要第二個構造函數不會調用它。然後,您可以在該構造函數中傳遞一個模擬對象,其中'target'方法被模擬。你會想要一個'WebTarget'的模擬,並且還要模擬任何'請求'返回。 –

回答

2

鑑於HttpService這個額外的構造函數:

public HttpService(Client client) { 
    this.client = client; 
} 

下面的測試將通過:

@RunWith(MockitoJUnitRunner.class) 
public class HttpServiceTest { 

    @Mock 
    private Client client; 
    @Mock 
    private WebTarget webTarget; 
    @Mock 
    private RequestEntity requestEntity; 

    private HttpService httpService; 

    @Before 
    public void setUp() { 
     this.httpService = new HttpService(client); 
    } 

    @Test 
    public void postJsonTest() { 
     String path = "https://stackoverflow.com/a/path"; 
     Map<String, ?> data = new HashMap<>(); 

     // the postJson method features this chained call: getTarget(path).request().post(entity, Map.class) 
     // so we have to mock each object created in that chain 

     // covers getTarget(path) 
     Mockito.when(client.target(Mockito.anyString())).thenReturn(webTarget); 

     // covers request() 
     Mockito.when(webTarget.request()).thenReturn(requestEntity); 

     // covers post() 
     Map<String, Object> expected = new HashMap<>(); 

     Mockito.when(requestEntity.post(Mockito.any(Entity.class), Mockito.eq(Map.class))).thenReturn(expected); 
     Map<String, ?> actual = httpService.postJson(path, data); 
     Assert.assertSame(expected, actual); 
    } 
} 

注:

  • 這依賴於提供新HttpService構造函數接受Client實例。
  • 通過HttpService的無參數構造函數中的靜態方法調用實例化Client的現有方法需要使用PowerMockito。更測試友好的方式是提供一種接受Client或者一個ClientFactoryClientFactory的默認實現是一個構造函數ClientBuilder.newClient()
  • postJson()方法具有鏈式調用(getTarget(path).request().post(entity, Map.class)),這就要求我們在嘲笑每個對象在返回鏈即Client,WebTargetRequestEntity
  • 我的例子溜冰超過細節,如通用類型RequestEntity和精確參數匹配選擇與一般參數匹配。你可以在那裏做出正確的選擇,因爲你最瞭解你的實現的具體細節和(b)你的測試的意圖,但是上面的測試至少表明你嘲笑一連串的調用需要每個對象在那條鏈上被嘲笑。
+1

是的,這或多或少與我的意見一致。謝謝你省去我自己寫這個的麻煩。 Upvoted。 –