简体   繁体   English

如何在单元测试中模拟 REST API?

[英]How to Mock REST API in unit testing?

I am using RestTemplate exchange HttpMethod.POST method to POST to an endpoint.我正在使用 RestTemplate exchange HttpMethod.POST方法来 POST 到端点。 In my test file I am testing for success of the POST method.在我的测试文件中,我正在测试 POST 方法是否success However with my current tests I am getting 401 Unauthorized error when POST request is made.但是,在我当前的测试中,发出 POST 请求时401 Unauthorized error I need help to Mock the API while making POST request in test file在测试文件中发出 POST 请求时,我需要帮助来模拟 API

Here is my main file这是我的主文件


@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;
    }
}

Here is my test file这是我的测试文件

@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());
    }
}


You are testing the logic inside DataTestRepo class, so you should not mock it.您正在测试 DataTestRepo 类中的逻辑,因此不应模拟它。 RestTemplate is a dependency inside DataTestRepo, so this is exactly what you need to mock. RestTemplate 是 DataTestRepo 中的一个依赖项,所以这正是您需要模拟的。 In general it should look like this inside your test:一般来说,它在你的测试中应该是这样的:

@InjectMocks
private DataTestRepo DataTestRepo;
@Mock
RestTemplate restTemplate;

Also, you will have to provide a return value for your mocked dependency, like this:此外,您必须为模拟的依赖项提供返回值,如下所示:

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

This is just a simple example.这只是一个简单的例子。 A good practice would be to check that the arguments passed to your mock equal to the expected ones.一个好的做法是检查传递给模拟的参数是否等于预期的参数。 One way would be to replace ArgumentMatchers.any() with the real expected data.一种方法是用真实的预期数据替换 ArgumentMatchers.any()。 Another is to verify it separately, like this:另一种是单独验证,像这样:

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

这是关于这个主题的一个很好的阅读: https : //reflectoring.io/spring-boot-web-controller-test/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM