Pelicer
Pelicer

Reputation: 1574

Mocking a dependencies in a method instead of the method itself

I developed a class the integrates my application with an API. When I first wrote the tests they were actually running it, but that came with some complications on the long term, so I decided to refator the tests by mocking my communication. Here's a snipped of one method and it's test:

The method confirmation:

public Response confirm(final String key) {
    final Response response;
    try {

        final HttpHeaders httpHeaders = this.initializeHeaders();
        final HttpEntity<String> entity = new HttpEntity<>(httpHeaders);
        final ResponseEntity<String> result = restTemplate.exchange(
                properties.getUri().concat(key),
                HttpMethod.GET,
                entity,
                String.class);

        response = this.handleResultJson(result);

    } catch (Exception e) {
        throw new IntegrationException(e.getMessage());
    }
    return response;
}

And its unit test:

@Test
void ShouldConfirm() {
    final Response response = new Response(
            true,
            UUID.randomUUID().toString(),
            "{\n" +
                    "    \"key\": \"dd227b53-550b-44a1-bb61-01016c3821ff\",\n" +
                    "    \"lastUpdated\": " + LocalDateTime.now() + ",\n" +
                    "}"
    );
    when(service.confirm(KEY)).thenReturn(response);
    assertEquals(service.confirm(KEY), response);
}

Even when i was writing it I found it strange. I doesn't seem like the mocks will call any code from the original method at all. But since I'm new to mockito, I kept going. After I ran sonar, I found out, not surprisingly, that my coverage went way down. I found out this question on the same matter, and Jon Skeet answer is correct all the way. My question is: how do I mock only the depedency, in my case, the atual response from the API?

Reading the question in the link I realized that the only thing I really need mocked is the following:

final ResponseEntity<String> result = restTemplate.exchange(
                properties.getUri().concat(key),
                HttpMethod.GET,
                entity,
                String.class);

Because I don't want to actually call the endpoint, just test the whole method. How do I accomplish this? Seems difficult since result is a variable inside the method I want to test.

Upvotes: 0

Views: 173

Answers (1)

Datta Diware
Datta Diware

Reputation: 602

You need to mock resttemplate something like below

@Mock
private RestTemplate restTemplate ;

restTemplate.exchange()

ResponseEntity<String> responseEntity = new ResponseEntity<String>("sampleBodyString",HttpStatus.OK);

when(restTemplate.exchange(
                           Matchers.anyString(), 
                           Matchers.any(HttpMethod.class),
                           Matchers.<HttpEntity<?>> any(), 
                           Matchers.<Class<String>> any()
                          )
                         ).thenReturn(responseEntity);

Upvotes: 1

Related Questions