'Mocking Unirest with mockito
I am in my starting programming phase and I wanted to ask about mocking Objects with Mockito, more specifically is the Unirest response. Let's say I have a database, and I dont what to bother it every time I do testing, and I want to use Mockito for that, but the problem is I am not sure how to create the fake "httpResponse" object that will come back. To give some context, I have attached my code:
/**
* This method lists the ID of the activity when requested.
*
* @return the list of all activities
*/
public JSONArray getActivites() {
HttpResponse<JsonNode> jsonResponse = null;
try {
jsonResponse = Unirest
.get("http://111.111.111.111:8080/activity")
.header("accept", "application/json")
.asJson();
} catch (UnirestException e) {
System.out.println("Server is unreachable");
}
JSONArray listOfActivities = jsonResponse.getBody().getArray();
return listOfActivities;
}
So what I had in mind, is to mock Unirest, and then when a .get method gets invoked, I would return a fake HttpResponse, problem is, I am not sure how to, I have looked online and couldn't really make much sense of it. Is it possible to do it 1 time with the actual Database, and then "Extract" the information and to use that every time for testing?
Solution 1:[1]
Sample Snippet with PowerMockRunner, PowerMockito and Mockito
@RunWith(PowerMockRunner.class)
@PrepareForTest({ Unirest.class})
public class TestApp{
@Before
public void setup() {
PowerMockito.mockStatic(Unirest.class);
}
@Test
public void shouldTestgetActivites() throws UnirestException {
when(Unirest.get(Client.DEFAULT_BASE_URL)).thenReturn(getRequest);
when(getRequest.asJson()).thenReturn(httpResponse);
when(httpResponse.getStatus()).thenReturn(Integer.valueOf(200));
assertThat(something).isEqualTo(true);
}
}
Solution 2:[2]
Instead of directly calling a static member, you could wrap the call in a wrapper class that can supply an HttpResponse based on some arguments. This is an interface that can easily be mocked in Mockito.
/**
* This is a wrapper around a Unirest API.
*/
class UnirestWrapper {
private HttpResponse<JsonNode> getResponse(String accept, String url) {
try {
return Unirest
.get(url)
.header("accept", accept)
.asJson();
} catch (UnirestException e) {
System.out.println("Server is unreachable");
}
// Or create a NULL HttpResponse instance.
return null;
}
}
private final UnirestWrapper unirestWrapper;
ThisClassConstructor(UnirestWrapper unirestWrapper) {
this.unirestWrapper = unirestWrapper;
}
/**
* This method lists the ID of the activity when requested.
*
* @return the list of all activities
*/
public JSONArray getActivites() {
HttpResponse<JsonNode> jsonResponse = this.unirestWrapper.getResponse("http://111.111.111.111:8080/activity", "application/json");
if (jsonResponse == null) {
return null;
}
JSONArray listOfActivities = jsonResponse.getBody().getArray();
return listOfActivities;
}
Or you could use power mocks...
Solution 3:[3]
In the meantime the orignal authors provide mocking support with unirest-mocks:
Maven:
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-mocks</artifactId>
<version>LATEST</version>
<scope>test</scope>
</dependency>
Usage:
class MyTest {
@Test
void expectGet(){
MockClient mock = MockClient.register();
mock.expect(HttpMethod.GET, "http://zombo.com")
.thenReturn("You can do anything!");
assertEquals(
"You can do anything!",
Unirest.get("http://zombo.com").asString().getBody()
);
//Optional: Verify all expectations were fulfilled
mock.verifyAll();
}
}
Solution 4:[4]
You can mock the HttpResponse
with Mockito.mock(HttpResponse.class)
and put to when get the body of this response to get your json. For example:
HttpResponse response = Mockito.mock(HttpResponse.class);
when(response.getBody()).thenReturn(readFileContent("my_response.json"));
this 'readFileContent' is just a method to read a file where I put my response. You can put your json to compare there
Solution 5:[5]
I solved similar task by using JUnit5 and Mockito. Class under test:
@Service
@RequiredArgsConstructor
@Profile("someProfile")
@Slf4j
public class SomeService {
@Value("${value1}")
private final String value1;
@Value("${value2}")
private final String value2;
private final ObjectMapper mapper;
private final CommonUtil commonUtil;
public boolean methodUnderTest(String inputValue) {
HttpResponse<String> result;
//some logic
try {
result = Unirest.get("url")
.header(header, value)
.routeParam("param", paramValue)
.asString();
if (result.getStatus() != 200) {
throw new MyException("Message");
}
//some logic
} catch (Exception e) {
log.error("Log error", e);
//some logic
}
}
}
And test:
@ExtendWith(MockitoExtension.class)
class SomeServiceTest {
@Mock
private CommonUtil commonUtil;
@Mock
private ObjectMapper mapper;
@Mock
HttpResponse httpResponse;
@Mock
GetRequest request;
private SomeService serviceUnderTest;
@BeforeEach
void setUp() {
this.serviceUnderTest = new SomeService("url", "valu1", mapper, commonUtil);
}
@Test
void methodUnderTest_whenSmth_ThenSmth() throws UnirestException {
try (MockedStatic<Unirest> unirest = Mockito.mockStatic(Unirest.class)) {
unirest.when(() -> Unirest.get(anyString()))
.thenReturn(request);
Mockito.when(commonUtil.encodeValue(Mockito.anyString())).thenReturn("123");
Mockito.when(request.header(anyString(), anyString())).thenReturn(request);
Mockito.when(request.routeParam(anyString(), anyString())).thenReturn(request);
Mockito.when(request.asString()).thenReturn(httpResponse);
Mockito.when(httpResponse.getStatus()).thenReturn(200);
Mockito.when(httpResponse.getBody()).thenReturn("true");
assertTrue(serviceUnderTest.methodUnderTest("123"));
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Mebin Joe |
Solution 2 | James |
Solution 3 | timomeinen |
Solution 4 | Suraj Rao |
Solution 5 | Rita |