Problem: I am writing a test case for a method from which a public static method with below code is called:
final File file = new File(filePath);
final OutputStream out = new FileOutputStream(file);
out.write(bytes);
out.close();
Now I need to mock the above calls.
What I have written:-
#Before
public void setUp() throws Exception{
File myFile = PowerMockito.mock(File.class);
FileOutputStream outStream = PowerMockito.mock(FileOutputStream.class);
PowerMockito.whenNew(File.class).withAnyArguments().thenReturn(myFile);
PowerMockito.whenNew(FileOutputStream.class).withAnyArguments().thenReturn(outStream);
doNothing().when(outStream).write(Matchers.any());
doNothing().when(outStream).close();
}
#Test
public void testMethod(){
PowerMockito.mockStatic(StaticClassUtil.class);
PowerMockito.when(StaticClassUtil.uploadFile(file.getBytes(), "dummy","dummy","dummy", null)).thenReturn("dummy");
}
While debugging I found No mock object at line :
final File file = new File(filePath);
Please suggest where I am getting wrong.
Most likely you missed one of the steps outlined in the documentation - probably you forgot to use #PrepareForTest for File.class and FileOutputStream.class.
But the real answer: you don't necessarily have to call new directly in your code. You can turn to dependency injection frameworks to do that for you, or simply have an OutputStream passed into your method under test. Because then you only pass a mocked object, and your need to mock those pesky calls to new() vanish in thin air. And you can stick with good old Mockito instead of PowerMock(ito).
Related
When I run the test method, I got the following output:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
You stub either of: final/private/equals()/hashCode() methods.
Those methods cannot be stubbed/verified.
Inside when() you don't call a method on mock but on some other object.
#Test
// #Ignore("Fails when run with build")
public void FailWhenImNotReady() throws ApplicationException, SystemException {
Map<String, String> rabbitMqProperties = new HashMap<String, String>();
rabbitMqProperties.put("amqp.addresses", "10.20");
rabbitMqProperties.put("amqp.virtualhost", "/pc");
rabbitMqProperties.put("amqp.username", "Deejay");
rabbitMqProperties.put("amqp.password", "deephouse");
rabbitMqProperties.put("amqp.port", "9805");
System.getProperties().putAll(rabbitMqProperties);
UserCredentials userCredentials = new UserCredentials();
userCredentials.setUserID("989864");
userCredentials.setAuthenticationSystem("djp");
EnterpriseMessageHeader enterpriseMessageHeader = new EnterpriseMessageHeader();
enterpriseMessageHeader.setUserCredentials(userCredentials);
LaunchAppRequest launchAppRequest = new LaunchAppRequest();
launchAppRequest.setUcn("4848");
launchAppRequest.setHeader(enterpriseMessageHeader);
when(userLogon.isUserLoggedIn(anyString(), anyString())).thenReturn(Boolean.TRUE);
when(Voice.lead()).thenReturn(76584l);
when(ConnectionFactoryProvider.getVocalist()).thenReturn(mock(Vocalist.class));
LaunchAppResponse response = AppLogicBean.launchApp(launchAppRequest);
assertFalse(response.isSuccessful());
assertEquals(response.getErrorMessage(), MusicProducer.PROXY_MSG);
}
You have two errors actually:
when(Voice.lead()).thenReturn(76584l);
when(ConnectionFactoryProvider.getVocalist()).thenReturn(mock(Vocalist.class));
You are trying to mock static methods. Mockito cannot be used to mock static methods. If you really want to do that, you should look closer at PowerMock.
The context
I have a simple method that I'm testing using the mockito library.
The problem
I have a error:
"[MockitoHint] ReceiveServiceTest.testGetFileDto (see javadoc for MockitoHint):
[MockitoHint] 1. Unused... -> at .ReceiveServiceTest.testGetFileDto(ReceiveServiceTest.java:46)
[MockitoHint] ...args ok? -> at ReceiveService.getFileDto(ReceiveService.java:28)
I dont understand way.
The code
#RunWith(MockitoJUnitRunner.class)
public class ReceiveServiceTest {
private List<File> filePaths = new ArrayList<>();
#InjectMocks
private ReceiveService receiveService;
#Mock
private FindFiles findfiles;
#Mock
private ReadByte readByte;
#Before
public void before() {
filePaths.add(new File("d://folder//test1_message_received"));
filePaths.add(new File("d://folder//test2_message_received"));
filePaths.add(new File("d://folder//test3_message_received"));
}
#Test
public void testGetFileDto() throws IOException {
// Given
byte[] resultByteArr = new byte[1028];
when(findfiles.getPathFiles()).thenReturn(filePaths);
when(readByte.readByteArrFromFile(new File("d://folder//test3_message_received"))).thenReturn(resultByteArr);
List<MessageDTO> result = receiveService.getFileDto();
//some assert
}
method
#Autowired
private FindFiles findFiles;
#Autowired
private ReadByte readByte;
public List<MessageDTO> getFileDto() throws IOException {
List<MessageDTO> fileDtos = new ArrayList<>();
for (File file : findFiles.getPathFiles()) {
fileDtos.add(new MessageDTO(Base64.getEncoder().encode(readByte.readByteArrFromFile(new File(file.getPath()))),
file.getName(), "zip", null));
}
return fileDtos;
}
I think mocks are not being initialized. Please initialize the mocks in the #Before method.
#Before
public void init() {
initMocks(this);
}
This should solve the problem I guess.
Here is solution for my problem. I added foreach loop. Now the mock works, but byte [] is different than what it should return.
// Given
byte[] mockByteArr = new byte [2048];
when(findfiles.getPathFiles()).thenReturn(filePaths);
for (File filePath : filePaths) {
when(readByte.readByteArrFromFile(new File(filePath.getPath()))).thenReturn(mockByteArr);
}
//When
List<MessageDTO> result = receiveService.getFileDto();
//Then
assertEquals(3, result.size());
assertEquals(mockByteArr, result.get(1).getContent());
Your problem is, that you create a new object in the following line:
when(readByte.readByteArrFromFile(new File("d://folder//test3_message_received"))).thenReturn(resultByteArr);
Mockito needs to know which real object is passed to the method so that it can return the appropriate thenReturn-value. So if you pass the actual reference into it, your code will work, but also only if you specify all the values which are listed. Otherwise you may get a NullPointerException.
By the way, calling new File(file.getPath()) seems redundant to me. You can just use file instead.
So with the following your code might work better:
when(readByte.readByteArrFromFile(filePaths.get(0)).thenReturn(resultByteArray);
but then you need to specify it for all entries.
Alternatively, use a Matcher instead:
when(readByte.readByteArrFromFile(ArgumentMatchers.any(File.class))).thenReturn(resultByteArr);
or specify the actual argument matching you require as matchers can be very powerful in that regard.
Previously the answer contained the following, which is still true, but not as concise as the answer above:
It's been a long time since I last used mocks (and I am even proud of it ;-)).
The message already states that one should consult the javadoc and there I found the following:
Those are hints - they not necessarily indicate real problems 100% of the time.
Nonetheless, I believe the problem is with the following statement:
when(readByte.readByteArrFromFile(new File("d://folder//test3_message_received"))).thenReturn(resultByteArr);
I think you need to specify a return for every entry in the filePaths or make the call more generic using Matchers.any() (or any other appropriate Matcher).
I Have a class for which i want to write a Junit unit test case.
public class ComparatorUtil {
public static Map<String, ValueDifference<Object>> compareJsonObject(Object srcObject, Object targetObject)
throws JsonGenerationException, JsonMappingException, IOException {
String initialJson = ConverterUtil.convertObjectToJson(srcObject);
String updatedJson = ConverterUtil.convertObjectToJson(targetObject);
Gson g = new Gson();
Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> firstMap = g.fromJson(initialJson, mapType);
Map<String, Object> secondMap = g.fromJson(updatedJson, mapType);
Map<String, MapDifference.ValueDifference<Object>> diffMap = Maps.difference(firstMap, secondMap).entriesDiffering();
return diffMap;
}
}
public class ConverterUtil {
public static String convertObjectToJson(Object o)
throws JsonGenerationException, JsonMappingException, IOException {
ObjectMapper mapperObj = new ObjectMapper();
return mapperObj.writeValueAsString(o);
}
}
Junit test case written by me:-
#RunWith(PowerMockRunner.class)
#PrepareForTest(ConverterUtil.class)
public class ComparatorUtilTest {
#Before
public void setUp() {
PowerMockito.mockStatic(ConverterUtil.class);
}
#Test
public void testValueDiff() throws JsonGenerationException, JsonMappingException, IOException {
TestObject srcObject = new TestObject();
srcObject.setColor("white");
srcObject.setId(1);
TestObject targetObj = new TestObject();
targetObj.setColor("white");
targetObj.setId(1);
targetObj.setSuffix("AA");
ComparatorUtil.compareJsonObject(srcObject, targetObj);
PowerMockito.verifyStatic(VerificationModeFactory.times(2));
ConverterUtil.convertObjectToJson(srcObject);
ConverterUtil.convertObjectToJson(targetObj);
}
}
When I am running the test class, I am getting a Null Pointer Exception as the initialJson and updatedJson is coming to be null. Can anyone please tell me where am I doing wrong?
So many things so wrong here.
You seem to assume how to use PowerMock. But what you put together simply doesn't make sense! You need to create a mocking specification using 'when().thenReturn()' for example.
Meaning: it is not enough to instruct PowerMock that a certain class will be mocked. You have to tell PowerMock about the actual values to be returned when these static methods are invoked.
so start by reading a good tutorial top to bottom. Don't use PowerMock for your own code, instead look how a tutorial solves a simple problem.
Then: PowerMock comes at certain cost. So you avoid using it. You rather should step back and look into reworking your code so that it can be tested without the need to mock static methods. You see, we are talking about code that transforms some input into some output. You should be able to write production and test code that requires no mocking at all for such situations. If at all, you should use frameworks such as Mockito - good production code can be tested without PowerMock.
More specifically: why is there a need to mock the static method? That seems to indicate that your ObjectMapper doesn't work in your unit test setup. It starts right there!
You see, a good unit test for your conversion method should simply look like:
assertThat(someConverterUnderTest.convert(fineTunedInput), is(expectedOutput));
That's it! You should design your converter to fully work in your unit test environment. And then all need for mocks is gone. In other words: you are currently testing implementation details. Instead you should always try testing the public contract of your methods. Testing implementation details is sometimes unavoidable, but as written before: the code you are showing here should really really be tested without mocks.
Then: even when you need mocks: the static methods are getting in your way. That is a clear signal that you shouldn't be using static here! Instead, you turn those elements that might require mocking either into parameters or into fields of your classes under test. Because then you can simply inject mocked objects. Which means that you don't need the PowerMock(ito) tooling anymore.
I am trying to use PowerMockito to mock the creation of the java.net.URL class in my code that I'm testing. Basically, I want to prevent the real HTTP request from occurring and instead 1) check the data when the request is made and 2) supply my own test data back on a mocked response. This is what I'm trying:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ URL.class, MockedHttpConnection.class })
public class Test {
URL mockedURL = PowerMockito.mock(URL.class);
MockedHttpConnection mockedConnection = PowerMockito.mock(MockedHttpConnection.class);
...
PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL);
PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection);
...
}
The code that I want to test looks like this:
URL wlInvokeUrl = new URL(wlInvokeUrlString);
connection = (HttpURLConnection) wlInvokeUrl.openConnection();
Earlier in my test scenario I mock the wlInvokeUrlString to match "MyURLString". I've also tried using various other forms of the whenNew line, trying to inject the mock. No matter what I try, it never intercepts the constructor. All I want to do is "catch" the call to openConnection() and have it return my mocked HTTP connection instead of the real one.
I have mocked other classes ahead of this one in the same script and these are working as expected. Either I need a second pair of eyes (probably true) or there is something unique about the URL class. I did notice that if I use "whenNew(URL.class).withAnyArguments()" and change the "thenReturn" to "thenAnswer" I could get it to trigger. Only problem is I never get the URL call for my code. What I see is an invocation of the 3-argument constructor for URL.class with all nulls for the parameters. Could it be this class is from the Java runtime and is bootstrapped by the test runner? Any help is much appreciated.
It's a common mistake when use PowerMockito.whenNew.
Note that you must prepare the class creating the new instance of MyClass for test, not the MyClass itself. E.g. if the class doing new MyClass() is called X then you'd have to do #PrepareForTest(X.class) in order for whenNew to work
From Powermock wiki
So, you need a bit change your test and add to #PrepareForTesta class which create a new instance of URLlike:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ URL.class, MockedHttpConnection.class , ConnectionUser.class})
public class URLTest {
public class URLTest {
private ConnectionUser connectionUser;
#Before
public void setUp() throws Exception {
connectionUser = new ConnectionUser();
}
#Test
public void testName() throws Exception {
URL mockedURL = PowerMockito.mock(URL.class);
MockedHttpConnection mockedConnection = PowerMockito.mock(MockedHttpConnection.class);
PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL);
PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection);
connectionUser.open();
assertEquals(mockedConnection, connectionUser.getConnection());
}
}
where:
public class ConnectionUser {
private String wlInvokeUrlString = "MyURLString";
private HttpURLConnection connection;
public void open() throws IOException {
URL wlInvokeUrl = new URL(wlInvokeUrlString);
connection = (HttpURLConnection) wlInvokeUrl.openConnection();
}
public HttpURLConnection getConnection() {
return connection;
}
}
I'm not sure the difference between .withParameterTypes(x) and .withArguments(x) but I believe you need to set it up as follows for your code to work. Give it a try and let me know if this doesn't help.
PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection);
PowerMockito.whenNew(URL.class).withArguments(Mockito.anyString()).thenReturn(mockedURL);
The problem is that the arguments of the real call are not matching with the expected in your mock.
PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL) will return mockedURL only the call is new URL("MyURLString").
If you change it to:
PowerMockito.whenNew( URL.class ).withParameterTypes( String.class )
.withArguments( org.mockito.Matchers.any( String.class ) ).thenReturn( mockedURL );
It will catch any string passed to the constructor URL(String) (even null) and return your mock.
When you tried
"whenNew(URL.class).withAnyArguments()" and change the "thenReturn" to
"thenAnswer" I could get it to trigger. Only problem is I never get
the URL call for my code. What I see is an invocation of the
3-argument constructor for URL.class with all nulls for the
parameters.
PowerMock will try to mock all constructors (org.powermock.api.mockito.internal.expectation.DelegatingToConstructorsOngoingStubbing.InvokeStubMethod at line 122) then it calls the first one (with 3 arguments) and mock its answer. But the subsequent calls will return the already mocked one because you told it to mock for any arguments. That's why you see just one call with null, null, null in your Answer.
I use Jersey and I have the following Rest function which returns a JSON string when my server is deployed:
#GET
#Path("getallemployees")
#Produces("application/json")
public Response getAllEmployees() {
//building the entity object which is List<Employee>
return Response.ok(entity).build();
}
I need to develop some unit tests (not integration testing) and I want to somehow mock the HTTPRequest that invokes this method and then get the json String. The best option would be to use mockito for this.
Is there any suggestion on how to do it ?
Thanks !!
The problem is that the method returns a Response object to the caller which is deep within the framework code. It doesn't return JSON strings.
You can use Mockito, if you need to mock something inside the method itself. That should work.
But you may need to take the value returned by the method and convert it to JSON like this if you are using Jackson with Jersey.
Response response = getAllEmployees();
Object retval = response.getEntity();
try {
ObjectMapper mapper = new ObjectMapper();
// I like this formatting. You can change it.
mapper.configure(Feature.INDENT_OUTPUT, true);
mapper.configure(Feature.WRITE_ENUMS_USING_TO_STRING, true);
mapper.configure(Feature.USE_ANNOTATIONS, false);
mapper.configure(Feature.FAIL_ON_EMPTY_BEANS, false);
mapper.setSerializationInclusion(Inclusion.NON_NULL);
mapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
mapper.getSerializationConfig().withSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
String json = mapper.writeValueAsString(retval);
... assert something about the string
} catch (JsonProcessingException e) {
// do something
} catch (IOException e) {
// do something
}
Some of this is guess work and speculation on my part but it may help. You could try using the Jersey Test Framework with the InMemoryTestContainerFactory:
It starts Jersey application and directly calls internal APIs to handle request created by client provided by test framework. There is no network communication involved. This containers does not support servlet and other container dependent features, but it is a perfect choice for simple unit tests.
It looks like to use it, all you need to do is extend JerseyTest and then override getTestContainerFactory() and follow the rest of the instructions, e.g.:
public class EmployeeResourceTest extends JerseyTest {
#Override
protected Application configure() {
// set up employee resource with mock dependencies etc...
return new ResourceConfig().registerInstances(employeeResource);
}
#Test
public void getAllEmployees() {
final String response = target("getallemployees").request().get(String.class);
// assert etc...
}
}
I used registerInstances instead of registerClasses in configure() as it looks like you can present a ready made Resource but set up with any mock dependencies you may want - although I haven't tried this myself.
The test class is a bit inflexible as you can only do one-time set up of dependencies in the configure() method, so it might be worth investigating using the MockitoJUnitRunner - although I'm not sure if it will work with the JerseyTest inheritance. It could allow you to do add behaviour to mocks in each #Test method, e.g.:
#Mock
private EmployeeResourceDependency dependency;
#InjectMocks
private EmployeeResource employeeResource;
// configure() as above but without mock setup up etc...
#Test
public void getAllEmployees() {
given(dependency.getEmployees()).willReturn(...);
// etc...
But like I said it might not be possible to mix them at all.