模拟请求/发布与mockito

时间:2017-08-30 19:07:15

标签: java unit-testing testing mockito junit4

我无法涵盖以下功能' postJson '使用测试(JUnit / Mockito),并且无法找到模拟线response = getTarget(path).request().post(entity, Map.class);

的方法
//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());
}

我无法在“请求”()之后找到制作测试代码的方法。向前。任何人都可以给我一个例子/解释我如何用mockito来覆盖这个功能?

1 个答案:

答案 0 :(得分:3)

Given this additional constructor on MyFunc1:

MyFunc2

The following test will pass:

$sql="insert into table_d values(";
        $data= mysqli_real_escape_string($connect,$worksheet->getCellByColumnAndRow($i,$row)->getValue());
echo $data; // it works and display data
if($i !== $highestColumnNum){//big if 
    if($data != ''){
    $sql.=$data;
    $sql.=',';
    }
    else{   
    $sql.=$data;
    $sql.=',';
    }
    }//end big if

else{ //big else
         if($data!='')
         $sql.=$data;
         else
         $sql.='';

        }//end big else

    }$sql.=')';
       mysqli_query($connect,$sql)or die("FUQUERY: '$sql'");

Notes:

  • This relies on providing a new HttpService constructor which accepts a public HttpService(Client client) { this.client = client; } instance.
  • The existing approach of instancing @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 = "/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); } } via a static method call inside the HttpService's no-arg constructor requires use of PowerMockito. A more test friendly approach is to provide a constructor which accepts a Client or perhaps a Client with the default implementation of the HttpService being Client
  • The ClientFactory method features a chained call (ClientFactory) which requires us to mock each object returned in that chain i.e. ClientBuilder.newClient(), postJson() and getTarget(path).request().post(entity, Map.class)
  • My example skates over specifics such as the generic type of Client and the choice of exact argument matchers vs. general argument matchers. You'll be able to make the right choice there since you know most about (a) the specifics of your implementation and (b) the intention of your test but the above test at least shows you that mocking a chain of calls requires each object in that chain to be mocked.