2017-08-30 164 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。 –