As i just started Mockito, I have below method that i want to test. In my YouTubeChannelImporter.java file there are both methods : readJsonFromUrl(String url) and readAll(rd)
public JSONObject readJsonFromUrl(String url) throws IOException,
JSONException {
InputStream is = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is,
Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JSONObject json = new JSONObject(jsonText);
return json;
} finally {
is.close();
}
}
I started with some rough idea.Below is the sample test case.
#Test
public void readJsonFromUrl() throws IOException, JSONException {
String urlTest="http://google.com/api";
YouTubeChannelImporter mockYoutube = mock(YouTubeChannelImporter.class);
YouTubeChannelImporter tubeChannelImporter =new YouTubeChannelImporter();
// URL url=new URL(urlTest);
// InputStream inputStream = mock(InputStream.class);
// when(url.openStream()).thenReturn(inputStream);
BufferedReader rd=mock(BufferedReader.class);
when(mockYoutube.readAll(rd)).thenReturn("{\"kind\":\"you\"}");
String jsonText="{\"kind\":\"you\"}";
JSONObject object=new JSONObject(jsonText);
assertEquals("{\"kind\":\"you\"}",tubeChannelImporter.readJsonFromUrl(urlTest).toString());
}
My issue is when i will test the function readJsonFromUrl(String url) then readAll(rd) should not execute. Rather mock should be in action here. I am aware this issue is because tubeChannelImporter.readJsonFromUrl(urlTest).toString() . Looking for any other way to achieve my goal.
Thanks
You're mocking one instance of your class, and then executing another - as you noticed, this does not achieve the intended result.
I think the easiest way of testing your method is with spying ("partial mocking"). With this technique, you'll have an actual instance of your class with only a single method, readAll mocked out:
#Test
public void readJsonFromUrl() throws IOException, JSONException {
// Set up the spied instance:
YouTubeChannelImporter tubeChannelImporter = spy(new YouTubeChannelImporter());
doReturn("{\"kind\":\"you\"}").when(tubeChannelImporter).readAll(any(Reader.class));
// Test the execution
String urlTest="http://google.com/api";
String jsonText="{\"kind\":\"you\"}";
JSONObject object=new JSONObject(jsonText);
assertEquals("{\"kind\":\"you\"}",tubeChannelImporter.readJsonFromUrl(urlTest).toString());
}
Personally, for a test like this where you have to read a file and there's not much else going on, I would read an actual file rather than mock out a BufferedReader. Then you just have to Assert on the JSONObject output from the call to readJsonFromUrl().
Your problems stem from trying to test against the private method readAll(). Try to test only your public methods in your tests (e.g. readJsonFromUrl()) and you'll find you have to jump through less hoops in your test code.
If your class already implements an Interface, then just write tests against the Interface.
If you find that you have a lot of private methods, perhaps your class is responsible for doing too much work, so factor methods out into their own class(es). Then you can test them in isolation.
If you have a maven project, the place to put your test files, to read from, is in /src/test/resources
Related
From the service I call the third party api using RestTemplate.
#RunWith(MockitoJUnitRunner.class)
public class ForceServiceTest {
#InjectMocks
private ForceService forceService;
#Mock
private RestTemplate restTemplate;
#Before
public void setup() {
forceService = new ForceService(config, restTemplate);
}
#Test
public void createTest_valid() throws JSONException {
/*Mockito.when(restTemplate.exchange(url, HttpMethod.POST, entity, CreateRecordResult.class))
.thenReturn(response);*/
Mockito.verify(restTemplate, Mockito.times(1))
.exchange(Mockito.anyString(),
Mockito.<HttpMethod> any(),
Mockito.<HttpEntity<?>> any(),
Mockito.<Class<?>> any());
forceService.createLead(lead);
}
}
I tried using both the any() method and directly specifying the values. Directly specifying the value in entity seems to be not the right way to test.
Below is the service class that I need to write test cases for.
#Component
public class ForceService {
private RestTemplate restTemplate;
public ForceService(ForceServiceConfig config, RestTemplate restTemplate) {
this.config = config;
this.restTemplate = restTemplate;
}
public String createLead(Lead lead) {
HttpHeaders headers = new HttpHeaders();
headers.set(AUTHORIZATION, getAccessToken());
headers.set(ACCEPT, APPLICATION_JSON);
headers.set(CONTENT_TYPE, APPLICATION_JSON);
LeadWrap leadWrap = new LeadWrap();
leadWrap.setFirstName(lead.getFirstName());
leadWrap.setLastName(lead.getLastName());
leadWrap.setEmail(lead.getEmail());
leadWrap.setPhone(lead.getPhone());
String jsonString;
try {
jsonString = new ObjectMapper().writeValueAsString(leadWrap);
} catch (IOException e) {
throw new RuntimeException(e);
}
HttpEntity<String> entity = new HttpEntity<>(jsonString, headers);
ResponseEntity<CreateRecordResult> exchange = restTemplate.exchange(
config.restUrl + "/v" + config.restVersion + "/sobjects/Lead/", HttpMethod.POST, entity,
CreateRecordResult.class);
if (exchange.getStatusCode().equals(HttpStatus.CREATED)) {
if (exchange.getBody() != null && exchange.getBody().success) {
LOGGER.info("Lead record created with Id " + exchange.getBody().id);
return exchange.getBody().id;
}
throw new RuntimeException("Record is not created");
} else {
LOGGER.error(RETURN_STATUS + exchange.getStatusCode());
throw new RuntimeException(RETURN_STATUS + exchange.getStatusCode());
}
The above test case returns the ResponseEntity exchange as null. Is there any solution for this to make the test case work for RestTemplate exchange call?
The verify needs to go after the call to the production code, in your case the createLead() call. You also are going to want to use matchers for your when call, which probably shouldn't be commented out. In cases like yours you generally don't need both the when and the verify. It just makes the test more complex and harder to read.
I use the verify if there is no return from the service call that I can assert on. In those cases I would wrap all the parameters of the when (if needed to get past a null pointer exception or other error) in any() such as any(HttpEntity.class) or anyString() so the params aren't ambiguous. Then you can use the verify to confirm the actual params are correct. This strategy is easier to maintain. Unfortunately, often it requires an argument captor to verify headers or other params are sent correctly. I say it's unfortunate because the tests become big and messy,
If I can assert on the result I often just use the when. In that case I would wrap the params with eq(), such as eq(httpEntity). In that case the HttpEntity class would need to have a good .equals() method or it would just use the default and probably isn't very helpful. But, it is generally pretty powerful.
You shouldn't use #InjectMocks and initialize in the setup. If you #InjectMocks it creates the instance and injects the mocks. You seem to wan to put a real config in so you would use the setup method or you could mock the config. I used a correct matcher, but you might have to refine them, for example switch some any() to eq() to truly test what you want to test. I also reordered so the action or the call to production call is before the verify. This test should get you started.
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
#RunWith(MockitoJUnitRunner.class)
public class ForceServiceTest {
private ForceService forceService;
#Mock
private RestTemplate restTemplate;
#Before
public void setup() {
forceService = new ForceService(new ForceServiceConfig(), restTemplate);
}
#Test
public void createTest_valid() throws Exception {
when(restTemplate.exchange(anyString(), eq(HttpMethod.POST),
any(HttpEntity.class),
eq(CreateRecordResult.class)))
.thenReturn(new ResponseEntity<>(new CreateRecordResult(), HttpStatus.CREATED));
forceService.createLead();
verify(restTemplate, times(1))
.exchange(eq("config.restUrl/vconfig.restVersion/sobjects/Lead/"),
any(HttpMethod.class),
any(HttpEntity.class),
eq(CreateRecordResult.class));
}
}
You need to tell Mockito what to return when the mock is called...
when(restTemplate.exchange(anyString(), any(), any(), any())).thenReturn(...
Insert the responseEntity you want returned from the call to exchange in the thenReturn.
#DCTID code saved my day. Along with that I faced the below issue and fixed it.
To mock the ResponseEntity's body, I created an object and set value to it. Else, it was not passing this condition - if (exchange.getBody() != null && exchange.getBody().success)
CreateRecordResult createRecordResult = new CreateRecordResult();
createRecordResult.success = true;
Mockito.when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class),
eq(CreateRecordResult.class)))
.thenReturn(new ResponseEntity<>(createRecordResult, HttpStatus.CREATED));
I'm trying to get to grips with JUnit & Mockito etc.
I currently have a method with the below line.
ObjectMetadata metadata = getMetadata(path.toString());
Is there any way I can mock it? I've tried things like the below
Whitebox.setInternalState(<mock of class>, "metadata", "abc");
but I just get
org.powermock.reflect.exceptions.FieldNotFoundException: No instance field named "metadata" could be found in the class hierarchy of com.amazonaws.services.s3.model.ObjectMetadata.
I think it's because previous use of Whitebox.setInternalState was with variables.
Any info. that might get me started would be appreciated.
If the method is protected then you dont need to use Powermockito, plain vanilla Mockito is enough and spying would do the trick here. Assuming the test class is in the same package as the production one, just in the src/test/java dir.
ClassUnderTest classUnderTestSpy = Mockito.spy(new ClassUnderTest()); // spy the object
ObjectMetadata objectMetadataToReturn = new ObjectMetadata();
doReturn(objectMetadataToReturn).when(classUnderTestSpy).get(Mockito.any(String.class));
I used any() matcher for the input but you can use a concrete value also.
Update If you cannot see the method then you would need to create an inner class that extends the prod one, implement the get method:
public class Test{
ObjectMetadata objectMetadataToReturn = new ObjectMetadata();
#Test
public void test(){
ClassUnderTestCustom classUnderTestCustom = new ClassUnderTestCustom();
// perform tests on classUnderTestCustom
}
private class ClassUnderTestCustom extends ClassUnderTest{
#Override
public String getMetadata(String path){
return objectMetadataToReturn ;
}
}
}
#PrepareForTest(ObjectMetadata.class)
public class PowerMockDemoTest {
private ObjectMetadata objectMetadata;
#Before
public void setUp() {
objectMetadata = new ObjectMetadata();
}
#Test
public void testMockNew() throws Exception {
ObjectMetadata mockObjectMetadata = mock(ObjectMetadata.class);
PowerMockito.whenNew(ObjectMetadata.class)
.withAnyArguments().thenReturn(mockObjectMetadata);
ObjectMetadata actualObjectmetadata = getMetadata(path.toString());
assertThat(actualObjectmetadata, is(mockObjectMetadata));
}
}
I am new to netty framework.We have a API Handler implementing SimpleChannelInboundHandler and overriding the ChannelRead0 function that takes ChannelHandlerContext and the FullHTTPRequest.Now I need to do unit testing mocking the inputs.
Can anyone help me with this.
Lets assume I want to test my MyContentExtractionHandler, which looks like this:
public class MyContentExtractionHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
#Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
int contentLenght = msg.content().capacity();
byte[] content = new byte[contentLenght];
msg.content().getBytes(0, content);
ctx.fireChannelRead(new String(content));
}
}
I will create a regular DefaultFullHttpRequest and use mockito to mock a ChannelHandlerContext. My unit test would look like this:
public class MyContentExtractionHandlerTest {
#Mock
ChannelHandlerContext mockCtx = BDDMockito.mock(ChannelHandlerContext.class);
MyContentExtractionHandler myContentExtractorHandler = new MyContentExtractionHandler();
#Test
public void myTest() throws Exception {
String content = "MyContentHello";
DefaultFullHttpRequest fullHttpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/my /uri", Unpooled.copiedBuffer(content.getBytes()));
myContentExtractorHandler.channelRead(mockCtx, fullHttpRequest);
BDDMockito.verify(mockCtx).fireChannelRead(content); //verify that fireChannelRead was called once with the expected result
}
}
Most possibly, your SimpleChannelInboundHandler will be the final handler. So instead of checking for fireChannelRead() check for whatever method you call after reading the message.
I have following Java code that I want to test. What I am having difficulty is figuring out how do I verify that call to handleAppVersionRequest , actually constructs AppVersionResponse object. Is there any way to do that using Mockito?
Here code is code for method:
class MyClass {
public void handleAppVersionRequest(String dataStr,
final int dataChannelId) {
String ver = "1.0";
final AppVersionResponse resp = new AppVersionResponse(ver);
Timber.d("Sending data %s", resp.toString());
sendResponse(dataChannelId, getGson().toJson(resp));
}
}
And here is method for test:
#Test
public void testHandleAppVersionRequest() throws Exception {
MyClass presenter = Mockito.spy(new MyClass());
String versionRequestJson = "{\"command\":1}";
when(presenter.getGson()).thenReturn(gSon);
presenter.handleAppVersionRequest(versionRequestJson,0);
// How do I verify that AppResponse object was constructed?
verify(presenter,times(1)).sendResponse(anyInt(),anyString());
}
If you must test the creation of the object during a unit test, you can extract a factory, mock it for your test, and then verify that the create method is called on it.
At the same time, consider spending some time looking at some tutorials for Mockito and unit testing in general, like this one. You should choose one class that is going to be the 'system under test'. Don't spy or mock this class! Instead, pass in mocks as dependencies that you will use to test the behaviour of your class.
Here is a factory extracted from your MyClass:
class AppVersionResponseFactory {
AppVersionResponse create(String version) {
return new AppVersionResponse(version);
}
}
Then the refactored version of your class where the dependencies (Gson and the factory) are passed in through the constructor:
class MyClass {
//dependencies that can now be mocked!
private final AppVersionResponseFactory appVersionResponseFactory;
private final Gson gson;
//pass the mockable dependencies in the constructor of the system under test!
public MyClass(AppVersionResponseFactory appVersionResponseFactory, Gson gson) {
this.appVersionResposeFactory = factory;
this.gson = gson;
}
public void handleAppVersionRequest(String dataStr, final int dataChannelId) {
String ver = "1.0";
AppVersionResponse resp = AppVersionResponseFactory.create(ver);
Timber.d("Sending data %s", resp.toString());
sendResponse(dataChannelId, gson.toJson(resp));
}
}
Now your test looks something like this:
//mocks
AppVersionResponseFactory mockAppVersionResposeFactory;
Gson mockGson;
//system under test
MyClass myClass;
#Before
public void setUp() {
mockAppVersionResposeFactory = Mockito.mock(AppVersionResponseFactory.class);
mockGson = Mockito.mock(Gson.class);
myClass = new MyClass(mockGson, mockAppVersionResposeFactory);
}
#Test
public void testHandleAppVersionRequest() throws Exception {
String versionRequestJson = "{\"command\":1}";
myClass.handleAppVersionRequest(versionRequestJson, 0);
verify(appVersionResposeFactory).create("1.0");
}
Please note that although your question asks for a way to verify the construction of an object, a better test would probably test the final outcome of that method i.e., that sendResponse was called with the correct dataChannelId and correct JSON. You can use the same techniques in this answer to do that i.e., extracting a dependency (perhaps a ResponseSender?), passing it in the constructor for your MyClass, mocking it in the test, then calling verify on it.
How is it possible to produce the same exception like during a real connection-error in robolectric tests?
I want to how the program acts if the network is currently not available. Is there a possibility to produce the same exception for my HttpClient?
I already tried:
Robolectric.getFakeHttpLayer().interceptHttpRequests(false); // with real network to a non existent IP
and
WifiManager wifiManager = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(false);
and
Robolectric.addPendingHttpResponse(404, null);
but none of them produces the same reactions like a real connection-loosing.
Thank you
I've checked Robolectric's FakeHttpLayer and haven't found way to simulate throwing an IOException.
So use mocking to make it working for you. First introduce HttpClientFactory (if you use HttpClient, you can use same approach for HttpUrlConnection):
public class HttpClientFactory {
public HttpClient createClient() {
return new DefaultHttpClient();
}
}
And now in your networking layer use factory instead of constructors (let for simplicity assume that it is synchronous):
public class HttpTransportLayer {
private final HttpClientFactory clientFactory;
public HttpTransportLayer() {
this(new HttpClientFactory());
}
// For tests only
HttpTransportLayer(HttpClientFactory clientFactory) {
this.clientFactory = clientFactory;
}
public String requestData(String url) {
HttpClient client = factory.createClient();
...
}
}
So now you can in tests use Mockito:
HttpClient mockedClient = mock(HttpClient.class);
#Before
public void setUp() {
HttpClientFactory factory = mock(HttpClientFactory.class);
when(factory.createClient()).thenReturn(mockedClient);
target = new HttpTransportLayer(factory);
}
#Test
public void whenIOExceptionThenReturnNull() {
when(mockedClient.execute(any(HtptUriRequest.class))).thenThrow(new IOException());
String data = target.requestData("http://google.com");
assertThat(data).isNull();
}
That is dummy test and usually nobody will return null in case of error.
You could also task look to some dependency injection framework like Dagger to minimise injection code.
If you use any good framework for networking like Retrofit or Volley then it is even simpler - you don't need to mock anything and just invoke you error callback.
Hope it helps