Search code examples
javaresttestingmockito

Spring Mockito Unable to mock RestTemplate


Hi!

I'm Unable to mock fetching data from GitHubApi To fetch data i use RestTemplate Exchange

Instead of taking data from github i want to mock my own

Expected :1
Actual   :11

Fetch Logic:

@Component
@Setter
public class GitHubApi {
    public List<GitHubRepository> getUserRepos(String user) {
        restTemplate = new RestTemplate();

        HttpHeaders headers = new HttpHeaders();
        addHeaders(headers);

         entity = new HttpEntity<>(headers);

        ResponseEntity<List<GitHubRepository>> response = restTemplate.exchange(
                GITHUB_API_URL + "/users/" + user + "/repos",
                HttpMethod.GET, entity,
                new ParameterizedTypeReference<List<GitHubRepository>>() {
                });
        return response.getBody();
    }
}

Test Logic:

    @Mock
    private RestTemplate restTemplate;

    @InjectMocks
    private GitHubApi gitHubApi;

    @Test
    public void getUserRepos_ShouldReturnRepositories() {
        String username = "user";

        GitHubRepository mockedRepository = GitHubRepository.builder()
                .id(1L)
                .name("repo1")
                .fullName("user/repo1")
                .build();
        List<GitHubRepository> expected = List.of(mockedRepository);

        ResponseEntity<List<GitHubRepository>> mockResponse = new ResponseEntity<>(expected, HttpStatus.OK);

        HttpHeaders headers = new HttpHeaders();
        addHeaders(headers);

        when(restTemplate.exchange(
                eq(GITHUB_API_URL + "/users/" + username + "/repos"),
                eq(HttpMethod.GET),
                any(HttpEntity.class),
                eq(new ParameterizedTypeReference<List<GitHubRepository>>() {})
        )).thenReturn(mockResponse);

        List<GitHubRepository> repositories = gitHubApi.getUserRepos(username);

        assertNotNull(repositories);
        assertEquals(1, repositories.size());
        assertEquals("repo1", repositories.getFirst().getName());
    }
}

I tries removing eq and any, tried adding HttpEntity instead of any, same with ParameterizedTypeReference


Solution

  • In GitHubApi you create new instance of restTemplate inside method, so Mockito not injecting restTemplate to class.

    You should make restTemplate as dependency:

    @Component
    @Setter
    public class GitHubApi {
        private final restTemplate; // <-- Here rest template is declared as dependency of this class.
    
        // constructor or use @RequiredArgsConstructor if you use lombok.
        public GitHubApi(RestTemplate restTemplate) {
            this.restTemplate = restTemplate;
        }
        public List<GitHubRepository> getUserRepos(String user) {
            // do not create restTemplate here, because it will rewrite mock with another instance.
            HttpHeaders headers = new HttpHeaders();
            addHeaders(headers);
    
             entity = new HttpEntity<>(headers);
    
            ResponseEntity<List<GitHubRepository>> response = restTemplate.exchange(
                    GITHUB_API_URL + "/users/" + user + "/repos",
                    HttpMethod.GET, entity,
                    new ParameterizedTypeReference<List<GitHubRepository>>() {
                    });
            return response.getBody();
        }
    }