【问题标题】:Mockito JUnit test for simple api call用于简单 api 调用的 Mockito JUnit 测试
【发布时间】:2019-12-23 19:43:39
【问题描述】:

我认为自己是单元测试的新手,对 Mockito 和 junit 完全陌生。我必须为一些简单的 api 调用编写单元测试。但是我的测试对我来说似乎毫无意义,我不知道我哪里出错了。我已向现有 Web 服务 ManagerWS.java 添加了一个方法,请参见下文。

ManagerWS.java 方法:

public String healthCheck(String userId) { 
    String healthCheckUrlEndpoint  = this.baseUrl()+"/health";
    logger.debug("Calling health check: {}", healthCheckUrlEndpoint);
    HttpHeaders healthCheckHeaders = new HttpHeaders();
    healthCheckHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
    healthCheckHeaders.add(USER_KEY, userId);
    healthCheckHeaders.add(TOKEN_NAME, TOKEN_VALUE);
    healthCheckHeaders.add(Constants.ACCEPT_LANGUAGE_HEADER, LocaleContextHolder.getLocale().toString());
    healthCheckHeaders.add(CORRELATION_HEADER, myService.get(AppLoggingMDCService.LOG_KEY_REQUEST_ID));
    HttpEntity<Object> request = new HttpEntity<Object>(healthCheckHeaders);
    ResponseEntity<String> response;        
    try {
        response = makeRequest(HttpMethod.GET, healthCheckUrlEndpoint, request, String.class); 
    } catch (Exception e) {
        logger.error("Exception encountered during health check", e);
        throw e;
    }       
    logger.debug("RESPONSE : http status: {} - body: {}", response.getStatusCode(), response.getBody());
    return response.getStatusCode().toString();
}

逻辑很简单。构造 url,创建标头并将标头添加到请求中。发出请求并从响应中提取状态码。这是我的测试。注意:该类使用 @RunWith(SpringRunner.class) 并且我使用 @Mock 用于依赖项@InjectMocks 用于本地实例 ManagerWS . ManagerWS.java 是被测试的服务类。

TEST-CLASS 测试方法:

    @Test
    public void testHealthCheck() throws Exception {
    //Given
    managerWS = new ManagerWS(templateFactory, configParamService, mdcService, env);    
    String url = "http://baseurl/health";
    HttpHeaders headers = new HttpHeaders();    
    HttpEntity<Object> request = new HttpEntity<Object>(headers);   
    ResponseEntity<String> response = new ResponseEntity<>(HttpStatus.OK);
    //when
    when(managerWS.makeRequest(HttpMethod.GET, url, request, String.class)).thenReturn(response);
    String actualStatus = response.getStatusCode().toString();  
    //then
    Assert.assertEquals("200",actualStatus);
}

对我来说,这个测试似乎很愚蠢(因为缺少一个连词)。我基本上将状态设置为“200”并断言我设置的是“200”。这并没有多大意义。对我来说,它实际上什么也没做。我尝试使用间谍(ManagerWS.class)。但我实际上是在没有完全理解的情况下抓住稻草。

SonarQube 仍然抱怨“单元测试未涵盖”。我完全不知道如何编写这个测试。我还必须对其他三个调用进行类似的测试。

我完全是测试新手,我看不出我的错误。请指教。

【问题讨论】:

标签: java unit-testing junit sonarqube mockito


【解决方案1】:

SonarQube 仍然抱怨“单元测试未涵盖”。

您的单元测试不会从要测试的方法的入口点进行测试:healthCheck(String),因此单元测试未涵盖它。 此外,您还模拟了您要测试的方法部分:

when(managerWS.makeRequest(HttpMethod.GET, url, request, String.class)).thenReturn(response);

所以确实你的方法看起来是错误的。
事实上,为这段代码编写单元测试看起来也是错误的,或者至少看起来像一个价值很少的白盒测试。
为什么 ? 你的逻辑取决于:

response = makeRequest(HttpMethod.GET, healthCheckUrlEndpoint, request, String.class); 

但是您可以知道它是否仅在运行时工作,并且运行 HTTP 服务器。 因此,您可以做的一件事就是模拟所有内容,监视被测对象并验证实现中的每个语句是否已执行:没有可读的测试,没有健壮的和很少/没有价值。

基本上依赖副作用的方法更适合作为集成测试进行测试:

  ManagerWS managerWS; // real ManagerWS implementation without mock

  @Test
  public void healthCheck() throws Exception {
    //Given
    String url = "http://baseurl/health";
    // When
    String actual managerWS.healthCheck(url);
    // Then
    String expected = "...";
    Assertions.assertEquals(expected, actual);
  }

附带说明,如果您使用 Spring,我建议您查看测试切片 @WebMvcTest,它专注于被测组件的 Web 部分。它主要允许测试 HTTP 部分/逻辑(标头、请求、响应)。

【讨论】:

    猜你喜欢
    • 2015-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-03
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 1970-01-01
    相关资源
    最近更新 更多