简体   繁体   中英

How to Mock REST API in unit testing?

I am using RestTemplate exchange HttpMethod.POST method to POST to an endpoint. In my test file I am testing for success of the POST method. However with my current tests I am getting 401 Unauthorized error when POST request is made. I need help to Mock the API while making POST request in test file

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. RestTemplate is a dependency inside DataTestRepo, so this is exactly what you need to mock. 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. 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/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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