PowerMokito doNothing() on private setter NullPointer - junit

Issue: Nullpointer exception thrown when attempting to execute PowerMockito.doNothing().
I need to create a partialMockObject class that will return a private method value and do nothing for another private setter method.
I am able to make it work if I replace doNothing() with supress() but would like to figure this out.
Code:
#Test
public void testPowerMockito() throws Exception
{
final String methodName1 = "Method1";
final String methodName2 = "Method2";
//Using PowerMockito
ObjectToTest partialMockObject = PowerMockito.spy(new ObjectToTest());
//Mock the private method, expect that a false
PowerMockito.doReturn(false).when( partialMockObject,methodName1 );
//Do Nothing on the void private setter
PowerMockito.doNothing().when( ObjectToTest.class,methodName2 );
String result = partialMockObject.methodToTest();
assertEquals("Fail","",result);
//Confirms that the private method was called
PowerMockito.verifyPrivate(partialMockObject).invoke(methodName1);
PowerMockito.verifyPrivate(partialMockObject).invoke(methodName1);
}
StackTrace:
'
java.lang.NullPointerException
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.java:68)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:43)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:104)

I have used PowerMockito extensively to try and deal with writing unit tests on some tricky legacy Java code. The best I can tell you is that not everything you think should work will work and that the online examples are of mixed age and quality. The spy works for doing the verifyPrivate, but I have had little success using PowerMockito to mock private method calls.
You do have a couple of possible moves: Make the private methods protected (and then you can just use Mockito partial mocking to do what you want to do here), or refactor the code so that you do not have these private methods and can #Mock the other object and thus have full mocking control over public calls. I have no idea what other constraints you are working under, of course.

Related

Unable to Mock functions inside static method Powermock

I am writing unit test for the below code using junit and mockito
public class Abc implements Runnable
{
private static ServerSocket server;
private static int port;
public Abc(int cPort)
{
port = cPort;
}
public void run()
{
init();
}
public static void init()
{
try {
server = new ServerSocket(port);
...something...
client.close();
}
}
catch(IOException e)
{
System.out.println("Exception inside init()...");
e.printStackTrace();
}
}
};
Unit test I have written
#RunWith(PowerMockRunner.class)
#PrepareForTest({ServerSocket.class})
public class abcTest {
#Mock (name = "server") //same name as private var.
ServerSocket mockServer;
#InjectMocks
Abc abc;
#Test
public void testInit() throws Exception {
int port = 1880;
Socket mockClient = Mockito.mock(Socket.class);
PowerMockito.whenNew(ServerSocket.class).
withArguments(anyInt()).thenReturn(mockServer);
abc = new Abc(port);
Abc.init();
PowerMockito.verifyNew(ServerSocket.class).withArguments(port);
}
};
But the call always go to original function definition. I am using junit 4.11 with mockito 2.28.2 and powermockito 2.0.2. I'm using java after a long time. Now its feel like kind of new. Please correct me if anything wrong in the code also.
You will need to change your PrepareForTest annotation
to #PrepareForTest({Abc.class}).
From the PowerMockito docu:
This annotation tells PowerMock to prepare certain classes for testing. Classes needed to be defined using this annotation are typically those that needs to be byte-code manipulated
In this case that refers to the class which creates the new instance of ServerSocket. ServerSocket itself is a non-final public class that does not require special handling from PowerMockito (instead Mockito can deal with this class on its own).
You could also change your test to do the following:
#Test
public void testInit() throws Exception {
int port = 1880;
ServerSocket mockServer = Mockito.mock(ServerSocket.class);
PowerMockito.whenNew(ServerSocket.class)
.withArguments(Mockito.anyInt()).thenReturn(mockServer);
Abc.port = port;
Abc.init();
PowerMockito.verifyNew(ServerSocket.class).withArguments(port);
}
(This first point is unrelated to whether the test fails or succeeds)
I do not know why you mix object's and static method behaviour together, but I think you should change that.In the test instead of creatic an ABC object, just could just set the static port variable directly.
Or alternatively change the whole ABC class into an object.
#InjectMocks failed for me as there is no default constructor
(Actually I got an error message in the console when trying to execute your code)
Additonaly you create a new instance of ABC in your test, which would have overwritten the things done by the annotations. Also as server is created during the init call, there is no need to inject a mock for it.
powermockito 2.0.2 actually depends on junit 4.12, so I am not sure what effects downgrading to an older version might have.
Socket mockClient seemed somewhat unrelated to the code your posted, so I removed it from my example in the answer, however as you use a client (I assume that is your Socket) in your code your probably need to do some mocking for that as well and provide the mock to the method accordingly.

Does Mockito support #Any #Inject Instance<> interface?

I have a init() method that use injected private instance<>. How can I test this class using JUnit or Mockito? I tried to make some fake class and add them to a list and set this list to my private field but I have this error
java.lang.IllegalArgumentException: Can not set javax.enterprise.inject.Instance field ......
MyClass is:
#Singleton
#Startup
public class HandlerManager {
#Any
#Inject
private Instance<RollbackHandler<RollbackData>> handlers;
private RollbackHandler<RollbackData> rollbackHandler;
#PostConstruct
public void init() {
for (RollbackHandler<RollbackData> bean : handlers) {
//do something
}
}
}
Any annotation is not processed by frameworks, unless you use custom work. you will have to define all those dependencies as mocks in your test using #Mock and call injectMocks() from before test methods such as setup(). It is a multi part problem.
Use constructor injection, field injection is evil. you still will be able to annotate your constructor with #Inject.
when(provider.iterator()).thenReturn(list.iterator);
works for me.
You can create a temporary list with concrete implementations of the RollbackHandler, and mock the iterator() method of your Instance<RollbackHandler<RollbackData>> object so that it returns the iterator of the temporary list.
Example:
private void mockIterator() {
Instance<RollbackHandler<RollbackData>> handlers = mock(Instance.class);
List<RollbackHandler<RollbackData>> handlersList = Collections.singletonList(new RollbackHandlerImpl<>());
when(handlers.iterator()).thenReturn(handlersList.iterator());
}

How to make a valid test using the mockito library?

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).

Test case for entity manager

Getting a null pointer exception on Mockito.when for the below code line.
when(entityManager.createQuery(any(String.class)).setParameter(any(String.class), any(String.class)).getSingleResult()).thenReturn("2");
Trying to mock entity manager which is declared as
#Mock
private EntityManager entityManager;
Any help to resolve this?
Complete test class
#RunWith(MockitoJUnitRunner.class)
public class ASDAOImplTest {
#InjectMocks
ASDAOImpl asdaoImpl=new ASDAOImpl();
#Mock
private EntityManager entityManager;
#Before
public void setUp()
{
ReflectionTestUtils.setField(asdaoImpl,"capLimit", 1);
}
#Test
#Ignore
public void validateCappingTest()
{
when(entityManager.createQuery(any(String.class)).setParameter(any(String.class), any(String.class)).getSingleResult()).thenReturn("2");
asdaoImpl.validateCapping("2");
}
}
Edit: Ah, spoke to soon. The error is here...
when(entityManager.createQuery(any(String.class)).setParameter(...)
entityManager is a mock. Per default, a mock will return null. So, entityManager.createQuery(...) will return null. Calling setParameter on null is a NPE.
What you need to insert is a query mock...
#Mock
private Query query;
...
// when createQuery is called, return the mocked query object (instead of null)
when(entityManager.createQuery(any(String.class)).thenReturn(query);
// make sure that setParameter returns this query object back (would otherwise also be NPE)
when(query.setParameter(any(String.class), any(String.class)).thenReturn(query);
// And return the desired result from getSingleResult
when(query.getSingleResult()).thenReturn("2");
Old answer:
Hard to say without the complete code, but a guess would be that you are misssing the Mockito initialization (the part that actually creates object for the variables annotated with #Mock). This can be done in at least two ways:
// Run the whole test with the Mockito runner...
#RunWith(MockitoJUnitRunner.class)
public class MyTestClass { ...
or...
// Do the Mockito initialization "manually"
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
Both ways will lead to Mockito creating all the objects where the variables are annotated with #Mock (it also handles #InjectMocks, etc.).
If this doesn't help, you will have to post more of your test class, otherwise probably noone can help.

Unable to mock URL class using PowerMockito/Mockito

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.