Gopal Betdur
Gopal Betdur

Reputation: 33

How do I mock Rest Template's getForEntity() method

I am new to mockito and need some help, probably some sample on how to mock Rest Template's getForEntity and postForEntity methods. Below is the code for which I want to write Junit test cases by mocking the getForEntity mehod.

SomeService.java

class SomeService
{
   //some private, static,  final data members
   public Map getService(String sNo, String uId, String en)
   {
      ResponseEntity <Map> response = new 
      RestTemplate().getForEntity("https://someurl.com/someService", 
      Map.class);
      Map body = response.getBody();
      //do something

      HttpEntity<?> request = new HttpEntity <>(payLoad, headers);
      //payload is Hash Map and headers is a LinkedMultiValueMap
      ResponseEntity <Map> response = new RestTemplate().postForEntity(url, 
      request, headers);
      return response.getBody(); 

   }   
}

I have tried doing something with @Mock and @InjectMocks.

TestSomeService.java

@RunWith(MockitoJunitRunner.class)
class TestSomeService
{
   @Mock
   RestTemplate restTemplate;
   @InjectMocks
   SomeService ser;
   /*Some data members*/
   @Before
   {
      HttpEntity <?> request = new HttpEntity<>(reqPayload, headers);
      Mockito.when(restTemplate.getForEntity("theUrl", 
      Map.class)).thenReturn(new ResponseEntity <Map>(someMap, 
      HttpStatus.OK));
      Mockito.when(restTemplate.postForEntity("anotherUrl", request, 
      Map.class)).thenReturn(new ResponseEntity <Map>(expectedMap, 
      HttpStatus.OK));

   }  
   @Test
   public void testGetService()
   {
       Map <String, Object> result = ser.getService("123", "abc", "QA");
   }    
}

Upvotes: 1

Views: 11735

Answers (5)

Yevgen
Yevgen

Reputation: 1667

If you are authorized to make changes to SomeService class, I would recommend you to do the following.

class SomeService
{
   //some private, static,  final data members
   public Map getService(String sNo, String uId, String en)
   {
      ResponseEntity <Map> response = getForEntity("https://someurl.com/someService", Map.class);
      Map body = response.getBody();
      //do something

      HttpEntity<?> request = new HttpEntity <>(payLoad, headers);
      //payload is Hash Map and headers is a LinkedMultiValueMap
      ResponseEntity <Map> response = postForEntity(url, request, headers);
      return response.getBody(); 
   }   
}

As you might have guessed getForEntity and postForEntity methods have been extracted and RestTemplate is instantiated within – doing its job undercover. And since you wanted to mock RestTemplate from the beginning, it's a good thing we have rid of it – now we can spy on our service without any objects to mock.

    @RunWith(MockitoJunitRunner.class)
    class TestSomeService
    {
       @InjectMocks
       @Spy
       SomeService ser;
       /*Some data members*/

       @Before
       {
          HttpEntity <?> request = new HttpEntity<>(reqPayload, headers);

          doReturn(new ResponseEntity <Map>(someMap, HttpStatus.OK))
            .when(ser).getForEntity("theUrl", Map.class));

          doReturn(new ResponseEntity <Map>(expectedMap, HttpStatus.OK))
            .when(ser).postForEntity("anotherUrl", request, Map.class));
       }

       @Test
       public void testGetService()
       {
           Map <String, Object> result = ser.getService("123", "abc", "QA");
       }    
    }

Upvotes: 0

dehasi
dehasi

Reputation: 2773

Are you sure that you want to mock especially a restTemplate?

What about not mocking the restTemplate but mocking an answer instead?

It'll help you to test the restTemplate behavior also. What if the restTemplate get 404 or 500?

That's why I suggest you use MockRestServiceServer

It helps to check all realish scenarios.

Upvotes: 0

Mansur
Mansur

Reputation: 1829

When you call specific value, you have to wrap it with ArgumentMatchers.eq(). However, you can use anyString(), any(Class class) and other ones as well. They are all self-explanatory. Mockito tutorial.

@Before
public void init (){
    MockitoAnnotations.initMocks(this);

    HttpEntity <?> request = new HttpEntity<>(reqPayload, headers);

    Mockito.when(restTemplate.getForEntity(ArgumentMatchers.eq("theUrl"),ArgumentMatchers.any(Map.class)))
            .thenReturn(new ResponseEntity <Map>(someMap, HttpStatus.OK));
}

Regarding to your structure.This way you can inject the RestTemplate through the constructor.

public class ServiceTester {

    @Mock
    private RestTemplate restTemplate;

    private Service service;

    @Before
    public void init (){
        MockitoAnnotations.initMocks(this);

        service = new Service(restTemplate);

        HttpEntity <?> request = new HttpEntity<>(reqPayload, headers);

        Mockito.when(restTemplate.getForEntity(ArgumentMatchers.eq("theUrl"),ArgumentMatchers.any(Map.class)))
                .thenReturn(new ResponseEntity <Map>(someMap, HttpStatus.OK));
    }


}

class Service {

    private RestTemplate template;

    @Autowired
    public Service(RestTemplate template) {
        this.template = template;
    }

    public Map doSomething () {
        // do something with template
    }
}

Upvotes: 2

LaurentG
LaurentG

Reputation: 11757

You have to inject RestTemplate your service SomeService. Currently, you're creating a new instance in the service. That means, you don't get the mock instance of RestTemplate but you get a fresh new instance of the real class RestTemplate.

You have to do something like this:

class SomeService
{
   @Inject
   private RestTemplate restTemplate;   

   //some private, static,  final data members
   public Map getService(String sNo, String uId, String en)
   {
      ResponseEntity <Map> response = restTEmplate.getForEntity("https://someurl.com/someService", 
      Map.class);
      ...
   }
}

Upvotes: 0

Sebastian
Sebastian

Reputation: 92

I mock a rest template like that

@RunWith(SpringRunner.class)
public class Clazz {

    @Mock
    private RestTemplate restTemplate;
}

So try to use SpringRunner instead of MockitoRunner maybe it will work

Upvotes: 0

Related Questions