【问题标题】:How to Mock REST API in unit testing?如何在单元测试中模拟 REST API?
【发布时间】:2020-01-26 18:07:18
【问题描述】:

我正在使用 RestTemplate exchange HttpMethod.POST 方法 POST 到端点。在我的测试文件中,我正在测试 POST 方法的 success。然而,在我目前的测试中,当发出 POST 请求时,我得到了401 Unauthorized error。在测试文件中发出 POST 请求时,我需要帮助来模拟 API

这是我的主要文件


@Component
public class DataTestRepo {

    private final RestTemplate restTemplate;
    private final String url;
    private final AllBuilder headersBuilder;

    public DataTestRepo(
            @Qualifier(Oauth.BEAN_NAME) AllBuilder headersBuilder,
            RestTemplate restTemplate, String url) {
        this.headersBuilder = headersBuilder;
        this.restTemplate = restTemplate;
        this.url = url;
    }
    public ResponseEntity<String> postJson(Set<String> results) {
        ResponseEntity<String> result = null;

        try {
            JSONObject jsonObject = new JSONObject(body);

            HttpEntity<String> request = new HttpEntity<String>(jsonObject.toString(), null);
            restTemplate.getMessageConverters().add(stringConvertor);
            result = restTemplate.exchange(url, HttpMethod.POST,
                    new HttpEntity<>(request, getHttpHeaders()), String.class);
         } 
        return result;
    }
}

这是我的测试文件

@RunWith(MockitoJUnitRunner.class)
@TestPropertySource
public class DataTestRepoTest {

    private static final String url = "http://localhost:8080/data/name";

    @Mock
    private DataTestRepo DataTestRepo;
    RestTemplate restTemplate = new RestTemplate();

    @Test
    public void restTemplateHttpPost_success() throws URISyntaxException {
        URI uri = new URI(url);
        Set<String> mockData = Stream.of("A","B").collect(Collectors.toSet());
        Map<String, String> body = new HashMap<>();
        body.put("Name", "Aws");
        JSONObject jsonObject = new JSONObject(body);

        HttpEntity<String> request = new HttpEntity<>(jsonObject.toString(), null);

        ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.POST,
                new HttpEntity<>(request, DataTestRepo.getHttpHeaders()), String.class);

        Assert.assertEquals(201, result.getStatusCodeValue());
    }
}


【问题讨论】:

    标签: java spring post mocking resttemplate


    【解决方案1】:

    你正在测试 DataTestRepo 类中的逻辑,所以你不应该模拟它。 RestTemplate 是 DataTestRepo 中的一个依赖项,因此这正是您需要模拟的内容。 一般来说,它在你的测试中应该是这样的:

    @InjectMocks
    private DataTestRepo DataTestRepo;
    @Mock
    RestTemplate restTemplate;
    

    此外,您还必须为您的模拟依赖项提供一个返回值,如下所示:

    Mockito.when(restTemplate.exchange(ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(new ResponseEntity<>(yourExpectedDataHere, HttpStatus.OK));
    enter code here
    

    这只是一个简单的例子。一个好的做法是检查传递给你的模拟的参数是否等于预期的参数。一种方法是将 ArgumentMatchers.any() 替换为真实的预期数据。另一种是单独验证,像这样:

    Mockito.verify(restTemplate, Mockito.times(1)).exchange(ArgumentsMatchers.eq(yourExpectedDataHere), ArgumentsMatchers.eq(yourExpectedDataHere), ArgumentsMatchers.eq(yourExpectedDataHere), ArgumentsMatchers.eq(yourExpectedDataHere));
    

    【讨论】:

    • 我之前用过上面的代码。我收到了java.lang.NullPointerException,所以我改为RestTemplate restTemplate = new RestTemplate(); 还有其他建议吗?谢谢
    • 你得到了 NPE,因为你的模拟依赖在你的逻辑中被调用时返回 null。您必须定义这个模拟对象应该返回什么。我已经修改了我的答案,请见上文。
    • 你的意思是这样Mockito.when(restTemplate.exchange(Mockito.eq(uri), Mockito.eq(HttpMethod.POST), Mockito.eq(new HttpEntity&lt;&gt;(request, processorDispatcherRepositoryImpl.getHttpHeaders())), Mockito.eq(String.class))).thenReturn(new ResponseEntity&lt;&gt;(result, HttpStatus.OK)); 然后Assert.assertEquals ?
    • 是的,但请记住,您正在测试DataTestRepo.postJson,所以Assert.assertEquals(yourExpectedData, dataTestRepo.postJson(Set.of("yourStringsHere")));
    • 这是我试过的Mockito.verify(restTemplate, Mockito.times(1)).exchange(Mockito.eq(uri), Mockito.eq(HttpMethod.POST), Mockito.eq(new HttpEntity&lt;&gt;(request)), Mockito.eq(String.class)); Assert.assertEquals(201, DataTestRepo.postJson(Stream.of("A","B").collect(Collectors.toSet()))); -------但是我收到了这个错误The method assertEquals(Object, Object) in the type Assert is not applicable for the arguments (int, void)我做错了什么吗?
    【解决方案2】:

    这是关于此主题的精彩阅读:https://reflectoring.io/spring-boot-web-controller-test/

    【讨论】:

      猜你喜欢
      • 2014-10-23
      • 2019-09-09
      • 2017-06-14
      • 1970-01-01
      • 1970-01-01
      • 2021-05-18
      • 1970-01-01
      • 2018-07-22
      • 1970-01-01
      相关资源
      最近更新 更多