I have a service in which I need to ask an outside server via rest for some information:
public class SomeService { public List<ObjectA> getListofObjectsA() { List<ObjectA> objectAList = new ArrayList<ObjectA>(); ParameterizedTypeReference<List<ObjectA>> typeRef = new ParameterizedTypeReference<List<ObjectA>>() {}; ResponseEntity<List<ObjectA>> responseEntity = restTemplate.exchange("/objects/get-objectA", HttpMethod.POST, new HttpEntity<>(ObjectAList), typeRef); return responseEntity.getBody(); } }
How can I write a JUnit test for getListofObjectsA()
?
I have tried with the below:
@RunWith(MockitoJUnitRunner.class) public class SomeServiceTest { private MockRestServiceServer mockServer; @Mock private RestTemplate restTemplate; @Inject private SomeService underTest; @Before public void setup() { mockServer = MockRestServiceServer.createServer(restTemplate); underTest = new SomeService(restTemplate); mockServer.expect(requestTo("/objects/get-objectA")).andExpect(method(HttpMethod.POST)) .andRespond(withSuccess("{json list response}", MediaType.APPLICATION_JSON)); } @Test public void testGetObjectAList() { List<ObjectA> res = underTest.getListofObjectsA(); Assert.assertEquals(myobjectA, res.get(0)); }
However the above code does not work, it shows that responseEntitty
is null
. How can I correct my test to properly mock restTemplate.exchange
?
We can use Mockito to mock the RestTemplate altogether. With this approach, testing our service would be as simple as any other test involving mocking. In the above JUnit test class, we first asked Mockito to create a dummy RestTemplate instance using the @Mock annotation.
Spring RestTemplate – HTTP GET Example getForObject(url, classType) – retrieve a representation by doing a GET on the URL. The response (if any) is unmarshalled to given class type and returned. getForEntity(url, responseType) – retrieve a representation as ResponseEntity by doing a GET on the URL.
To mock the external service, we can abstract all its logic within an interface which we can implement elsewhere and use it by our functional tests, returning the outcome we need to test the behavior of our application.
You don't need MockRestServiceServer
object. The annotation is @InjectMocks
not @Inject
. Below is an example code that should work
@RunWith(MockitoJUnitRunner.class) public class SomeServiceTest { @Mock private RestTemplate restTemplate; @InjectMocks private SomeService underTest; @Test public void testGetObjectAList() { ObjectA myobjectA = new ObjectA(); //define the entity you want the exchange to return ResponseEntity<List<ObjectA>> myEntity = new ResponseEntity<List<ObjectA>>(HttpStatus.ACCEPTED); Mockito.when(restTemplate.exchange( Matchers.eq("/objects/get-objectA"), Matchers.eq(HttpMethod.POST), Matchers.<HttpEntity<List<ObjectA>>>any(), Matchers.<ParameterizedTypeReference<List<ObjectA>>>any()) ).thenReturn(myEntity); List<ObjectA> res = underTest.getListofObjectsA(); Assert.assertEquals(myobjectA, res.get(0)); }
This is an example with the non deprecated ArgumentMatchers class
when(restTemplate.exchange( ArgumentMatchers.anyString(), ArgumentMatchers.any(HttpMethod.class), ArgumentMatchers.any(), ArgumentMatchers.<Class<String>>any())) .thenReturn(responseEntity);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With