2
@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;
    }
}
Community
  • 1
  • 1
c2340878
  • 389
  • 1
  • 4
  • 12
  • The problem is that the `RestTemplate` you are mocking is not passed into `Service` as a dependency. You are creating a `new RestTemplate()` inside the `isEnabled` method, it cannot be mocked that way. – Snackoverflow Aug 14 '20 at 12:15
  • Also, you probably meant to use `anyThing()` instead of `requestTo(Mockito.anyString())` which would just expect an empty string as URL, failing. – Snackoverflow Aug 14 '20 at 12:18

3 Answers3

3

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.

Rafal G.
  • 4,252
  • 1
  • 25
  • 41
  • I suppose your comment is the right one, although I am not sure how to fix my problem. If I can not create restTemplate bean. Is there any other I can do to mock a restTemplete? and actually I just need to mock the response of a get call. Is there anyway to do this? – c2340878 Feb 24 '17 at 20:07
1

This is not an answer to your question, but just in case anyone comes across this question in 2021… With Spring Boot Testing, you may want to take advantage of testing the REST slice only with @RestClientTest. This creates a RestTemplateBuilder bean only by default, if you want an auto-wired RestTemplate just add one bit of configuration as below. (The example is in Kotlin, using Java instead remains as an excercise to the reader.)

@AutoConfigureWebClient(registerRestTemplate = true)
@RestClientTest(Service::class)
class AdkClientTest @Autowired constructor(
    private val mockRestServiceServer: MockRestServiceServer,
    private val service: Service
) {
    // …
}
Michael Piefel
  • 18,660
  • 9
  • 81
  • 112
0

I think you mean you want to use RestTemplate which is provided by spring, so you should createServer after the spring autowired the RestTemplate. I think you can do it like this:

@RunWith(MockitoJUnitRunner.class)
public class FeatureFlipperManagerTest {
    @Autowired
    RestTemplate restTemplate;

    Service service;
    MockRestServiceServer mockServer;

    @Before
    public void init() {
        service = new Service(); 
        service.setRestTemplate(restTemplate);
        // If you have autowired restTemplate in Service, you can just autowired the service
        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);
    }
}
hiroyukik
  • 713
  • 1
  • 6
  • 14
xierui
  • 1,047
  • 1
  • 9
  • 22