Vimal's Way
Vimal's Way

Reputation: 33

How to mock a service class calling Rest API and getting ResponseEntity as Response

I have below classes.

@Service
class RestService {
@Autowired
private RestTemplate restTemplate;

public ResponseEntity<String> callService(String param) {
return restTemplate.exchange(....);
}
}

@Service
class CallingService{
@Autowired
private RestService restService;

public ResponseDTO getResponse(String param) {
ResponseEntity<String> response = restService.callService(param);
ResponseDTO responseDTO = convert(response)// JSON Convertor here
return responseDTO;
}
}

Now I want to write test class for CallingService class.

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.IOException;

import javax.xml.datatype.DatatypeConfigurationException;

import org.apache.cxf.helpers.IOUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.jupiter.api.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

@RunWith(MockitoJUnitRunner.class)
@SpringBootTest
class CallingServiceTest{
@InjectMocks
private CallingService service;
@Mock
private RestService restService;

@Test
public testGetResponse(){
ResponseDTO dto = createDummyObject();

HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_JSON);

ResponseEntity<String> responseEntity = new ResponseEntity<>("response message", header, 
HttpStatus.OK);

when(restService.callService(Mockito.anyString())).thenReturn(responseEntity);
// mocking converter here
 dto = service.getResponse("param");
//assert conditions here onwards
}
}

The invocation at line service.getResponse("param") gives NullPointerException. On debugging I found that response received in CallingService.getResponse() is null (i.e. restService.callService(param) returned null) and hence code broken into convert() method.

I tried with a lot of code manipulations but no luck. Hope anyone might have answer for this.

Upvotes: 1

Views: 2396

Answers (3)

Vimal&#39;s Way
Vimal&#39;s Way

Reputation: 33

I finally found a workaround by combining flavours of above two answers.

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

import org.apache.cxf.helpers.IOUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

@RunWith(MockitoJUnitRunner.class)
@SpringBootTest
public class CallingServiceTest{
@InjectMocks
private CallingService service;
@Mock
private RestService restService;
@BeforeEach
public void setup(){
MockitoAnnotations.init(this);
}

@Test
public testGetResponse(){
ResponseDTO dto = createDummyObject();

HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_JSON);

ResponseEntity<String> responseEntity = new ResponseEntity<>   ("response message", header, HttpStatus.OK);

     when(restService.callService(Mockito.anyString())).thenReturn(responseEntity);
// mocking converter here
dto = service.getResponse("param");
//assert conditions here onwards
}
}

Upvotes: 1

SSK
SSK

Reputation: 3766

Based on your import you are using a combination of Junit4 and Junit5. This will not work properly.

Steps to run with Junit5

  1. Change your imports to org.junit.jupiter.api.*
  2. Change @Before to @BeforeEach.
  3. Remove @SpringBootTest not required with Junit5
  4. Change @RunWith(MockitoJUnitRunner.class) to @ExtendWith(MockitoExtension.class)

Please find the changed code below

@ExtendWith(MockitoExtension.class)
class CallingServiceTest{
@InjectMocks
private CallingService service;
@Mock
private RestService restService;

@Test
public testGetResponse(){
ResponseDTO dto = createDummyObject();

HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_JSON);

ResponseEntity<String> responseEntity = new ResponseEntity<>("response message", header, 
HttpStatus.OK);

when(restService.callService(Mockito.anyString())).thenReturn(responseEntity);
// mocking converter here
 dto = service.getResponse("param");
//assert conditions here onwards
}
}

If you want to run with Junit4 change your import for @Test to import org.junit.Test from import org.junit.jupiter.api.Test

Either one of the solutions will work.

Upvotes: 0

George
George

Reputation: 3030

You can't use both @RunWith(MockitoJUnitRunner.class) and @SpringBootTest. They're both setting up JUnit Rules and you can only have one rule active.

You need to use Spring annotations. Instead of @Mock use @MockBean so Spring can properly inject it to the service.

@SpringBootTest
class CallingServiceTest{
@Autowired
private CallingService service;
@MockBean
private RestService restService;

@Test
public testGetResponse(){
ResponseDTO dto = createDummyObject();

HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_JSON);

ResponseEntity<String> responseEntity = new ResponseEntity<>("response message", header, 
HttpStatus.OK);

when(restService.callService(Mockito.anyString())).thenReturn(responseEntity);
// mocking converter here
 dto = service.getResponse("param");
//assert conditions here onwards
}
}

Alternatively, you can use just Mockito since you don't really need to initialize SpringContext for this test I think.

@RunWith(MockitoJUnitRunner.class)
class CallingServiceTest{
@InjectMocks
private CallingService service;
@Mock
private RestService restService;

@Test
public testGetResponse(){
ResponseDTO dto = createDummyObject();

HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_JSON);

ResponseEntity<String> responseEntity = new ResponseEntity<>("response message", header, 
HttpStatus.OK);

when(restService.callService(Mockito.anyString())).thenReturn(responseEntity);
// mocking converter here
 dto = service.getResponse("param");
//assert conditions here onwards
}
}

Upvotes: 0

Related Questions