Search code examples
javaspringmockitoresttemplatemockrestserviceserver

How to mock RestTemplate with MockRestServiceServer?


@RunWith(MockitoJUnitRunner.class)
public class FeatureFlipperManagerTest {
    @Autowired
    RestTemplate restTemplate = new RestTemplate();
    @Autowired
    Service service = new Service();
    MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate);

    @Test
    public void test() throws Exception {
      mockServer.expect(requestTo(Mockito.anyString()))
                .andRespond(withSuccess("{\"enabled\":true}", MediaType.APPLICATION_JSON));
        boolean res = service.isEnabled("xxx");
        mockServer.verify();
        Assert.assertEquals(true, res);
    }
}

I have MockRestServiceServer to mock restTemplete in a service. But it always fail. it shows the error as java.lang.AssertionError: Further request(s) expected 0 out of 1 were executed. Any one could let me know where I did not do it right.

The service itself will looks as this:

public class Service{
    public boolean isEnabled(String xxx) {
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> response = restTemplate.getForEntity("someurl",String.class);
        if(...)return true;
        return false;
    }
}

Solution

  • First of all, your Service class creates a new instance of RestTemplate on every request. I cannot stress enough how bad practice it is. Create a bean of type RestTemplate and inject it into your Service bean (it is most likely already created - depending on the Spring MVC version you are using).

    Once you have it, then both RestTemplates: one in your Service bean and one injected into FeatureFlipperManagerTest will be the same and testing with MockRestServiceServer will be possible.

    EDIT - to be more explicit:

    Modify your Service class to:

    @Component
    public class Service {
    
        private RestTemplate restTemplate;  
    
        @Autowired 
        public Service(RestTemplate restTemplate) {
            this.restTemplate = restTemplate;
        }
    
        public boolean isEnabled(String xxx) {
            ResponseEntity<String> response = restTemplate.getForEntity("someurl",String.class);
            if(...)return true;
            return false;
        }
    }
    

    and your test class to:

    @RunWith(MockitoJUnitRunner.class)
    public class FeatureFlipperManagerTest {
        @Autowired
        RestTemplate restTemplate;
    
        @Autowired
        Service service;
    
        MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate);
    
        @Test
        public void test() throws Exception {
          mockServer.expect(requestTo(Mockito.anyString()))
                    .andRespond(withSuccess("{\"enabled\":true}", MediaType.APPLICATION_JSON));
            boolean res = service.isEnabled("xxx");
            mockServer.verify();
            Assert.assertEquals(true, res);
        }
    }
    

    If this fails with exception saying that there is no RestTemplate bean present then please paste info about version of Spring (Spring Boot?) you are using.