How to use MockedStatic verify on static methods? - java

I have the following mocks for 2 different static method; UnitConversion.isCompatible() and Logging.error() that are called in my service method.
Here is my test method:
myService.demoMethod();
try (MockedStatic<UnitConversion> unitConversion= mockStatic(UnitConversion.class)) {
unitConversion.verify(never(), () -> UnitConversion.isCompatible(any()));
UnitConversion.isUnitsCompatible(any());
}
try (MockedStatic<Logging> logging = mockStatic(Logging.class)) {
logging.verify(times(1), () -> Logging.error(any()));
Logging.error(any();
}
The first method is never called while the second one is called one time when I debug. It is ok, but the test gives "Wanted but not invoked" error for the second method. I am not sure if I should call the static methods in try blocks, because I already call my service method that calls the static methods.
So, how can I verify the static method calls using MockedStatic (not powermock, etc)? SHould I call them in try blocks?
Update: I use the following approach, but it still gives "Wanted but not invoked" error even if breakpoint hit once to the static method called from the service method.
// I also try to call the service method under the test here again
demoService.create(request);
try (MockedStatic<LoggingUtils> mock = mockStatic(LoggingUtils.class)) {
// as the static method is void, no need to stub and not use "when()" in here
// I call the service method under the test
demoService.create(request);
// verify that the method is being invoked
mock.verify(times(1), () -> LoggingUtils.error(any(), any()));
}
Update-II:
demoService:
public CommandDTO create(final PurchaseRequest request) {
// code omitted
addLog();
return CommandDTO.builder().uuid(purchase.getUuid()).build();
}
private void addLog() {
LoggingUtils.error("error", null);
}
LoggingUtils:
public class LoggingUtils {
public static void error(String var1, Throwable var2) {
log.error(getString(var1), var2);
}
}

I can see a few issues in this snippet:
try (MockedStatic<UnitConversion> unitConversionMockStatic = mockStatic(UnitConversion.class)) {
unitConversionMockStatic.verify(never(), () -> UnitConversion.isCompatible(any()));
UnitConversion.isUnitsCompatible(any());
}
you verify that the method is being called before calling it
as you specified that you expect never(), this passes
you call the method with the argument matcher. This is illegal - you need to call with normal parameter.
Thus, the structure of the test should be
try (MockedStatic<UnitConversion> unitConversionMockStatic = mockStatic(UnitConversion.class)) {
// if needed, stub the static method with when
// call the static method (probably indirectly, via service under thest)
UnitConversion.isUnitsCompatible(10);
// verify that the method is being invoked
unitConversionMockStatic.verify(times(1), () -> UnitConversion.isCompatible(any()));
}
Note the usage of try-with-resources, MockStatic is no longer in effect when it is closed (which happens when you exit from the try-with-resources block). Thus, you must invoke the method under test (which calls the static method) inside of the try-with-resources block.

Related

How to use mockito / powermockito to make an instantiated dependent class throw an exception on a specific method call

This is the code I want to test. It's pretty straight forward
class FileHandler {
public boolean deleteFiles(String path) {
// mock this to throw an exception
}
public static FileHandler instatiateNew(String location) {
// creates a FileHandler
}
}
class B {
public void action {
try {
FileHandler x = FileHandler.instantiateNew("asd");
x.deleteFiles();
} catch (Exception e) {
// untested code I want to reach
}
}
}
I now want to test method action and see how it handles x.deleteFiles() throwing an exception. I have tried doThrow, thenThrow and ran into errors (NullPointerException, probably because I stubbed the method wrongly) or the method not throwing the exception in the end.
I am also confused whether I need Powermockito or not. I will now try an approach, where I mock the whole FileHandler class. As I need to mock the static instantiation method I will need PowerMock for that. But I would prefer a less heavy handed solution. Does it exist?
my partial class mock is now:
FileHandler mockHandler = Mockito.mock(FileHandler.class)
Mockito.mock(mockHandler.deleteFiles(Mockito.anyString()).thenThrow(Exception.class);
PowerMockito.mockStatic(FileHandler.class);
PowerMockito.when(FileHandler.instantiateNew(Mockito.anyString())).thenReturn(mockHandler())
Which is still causing issues, maybe becasue FileHandler is used elsewhere and mockStatic kills all other usages.
Make sure all the necessary members are properly arranged so that the test can be exercised.
For example
RunWith(PowerMockRunner.class)
#PrepareForTest({FileHandler.class})
public class MyTestCase {
public void testdeleteFilesErrorHandling() throws Exception {
//Arrange
//instance mock
FileHandler handler = Mockito.mock(FileHandler.class);
Mockito.when(handler.deleteFiles(anyString())).thenThrow(new Exception("error message"));
//mock static call
PowerMockito.mockStatic(FileHandler.class);
Mockito.when(FileHandler.instantiateNew(anyString())).thenReturn(handler);
B subject = new B();
//Act
subject.action();
//Assert
//perform assertion
}
}
Reference: Using PowerMock with Mockito
using mockStatic was not an option for me as FileHandler was used in setup and teardown of the tests and this heavy handed approach would cause problems.
What saved me where stub and method from org.powermock.api.support.membermodification.MemberModifier.
FileHandler mock = Mockito.mock(FileHandler.class);
Mockito.when(mock.deleteFiles(anyString()))
.thenThrow(Exception.class);
stub(method(FileHandler.class, "instantiateNew", String.class)).toReturn(mock);
Note that it is necessary to prepare class FileHandler through a test class decorator and to use the PowerMockRunner. This is necessary as we are stubbing a static method on FileHandler. This is done so:
#PrepareForTest({FileHandler.class})
#RunWith(PowerMockRunner.class)
public class MyTest extends MyBaseTestClass {
#Test
public void myTest() {
// write test code from above here.
}
}

Byte Buddy not preserving return value when .andThen used

I am trying to use Byte Buddy to execute some additional logic when a method is done. Here is the sample code:
T proxyClient = JAXRSClientFactory.fromClient(client, classType, true);
this.configureHttpConduit(conduit, invocationTimeout);
Class buddy = new ByteBuddy()
.subclass(classType)
.method(ElementMatchers.isAnnotatedWith(Path.class))
.intercept(MethodDelegation.to(proxyClient)
.andThen(MethodCall.run(new CloseConnection())))
.make()
.load(this.getClass().getClassLoader(),
Default.INJECTION)
.getLoaded();
return (T) buddy.newInstance();
static class CloseConnection implements Runnable {
void close() {
System.out.println("close connection called");
}
#Override
public void run() {
close();
}
}
When I chain the delegation with the .andThen call, the original caller to this instance loses the return values that was from the "proxyClient" object which it used to invoke a method call on it earlier. Am I using Byte Buddy wrong?
Basically I want to add some additional logic to the end of a method (inside the original method or adding another method call does not matter), but at the same time preserving the return value of the original method call.
This is by design. For every Implementation that you chain via andThen, Byte Buddy expects an empty stack for the next block. Thus, the last implementation is responsible for the return.
The idea of Byte Buddy is to put as much logic as possible into the interceptor. I would suggest to you to write your own interceptor that invokes the delegate and then invokes the close connection. This gives you also full control over the call conditions like closing in a finally block:
public class MyInterceptor<T> {
final T proxyClient;
#RuntimeType
public Object intercept(#Origin Method method,
#AllArguments Object[] args) throws Throwable {
try {
return method.invoke(proxyClient, args);
} finally {
// do your completion logic here
}
}
}
This can of course be improved in terms of performance. Have a look at the #Pipe annotation for that.

Mockito: wait for an invocation that matches arguments

I'm writing a selenium test and verifying the server behavior with mockito. Specifically, when a button is clicked, I want to make sure the page controller calls a particular method on a dependency which I've mocked.
Because it is a selenium test, I need to wait for the mock to be invoked in another thread, so I'm using mockito timeout.
verify(myMock, timeout(5000).times(1)).myMethod("expectedArg");
The trouble that I'm having is that myMethod is called many times... rather than waiting for an invocation that matches the expected arguments, timeout only waits for the first invocation.
If I use Thread.sleep(50000) rather than timeout(50000), it works as expected... but that's dirty so I'm hoping to avoid it.
How do I wait for myMethod to be invoked with the expected input?
If you are able to set a fixed number of calls to expect, it can be done with an ArgumentCaptor:
import static org.hamcrest.CoreMatchers.hasItem;
#Captor ArgumentCaptor<String> arg;
#Before
public void setUp() throws Exception {
// init the #Captor
initMocks(this);
}
#Test
public void testWithTimeoutCallOrderDoesntMatter() throws Exception {
// there must be exactly 99 calls
verify(myMock, timeout(5000).times(99)).myMethod(arg.capture());
assertThat(arg.getAllValues(), hasItem("expectedArg"));
}
Another way is to specify all the expected values to verify, but those need to be provided in the exact order that they are invoked. The difference to the above solution is that this doesn't fail even if the mock is additionally called with some non-verified arguments. In other words, no need to know the number of total invocations. Code example:
#Test
public void testWithTimeoutFollowingCallsDoNotMatter() throws Exception {
// the order until expected arg is specific
verify(callback, timeout(5000)).call("firstExpectedArg");
verify(callback, timeout(5000)).call("expectedArg");
// no need to tell more, if additional calls come after the expected arg
// verify(callback, timeout(5000)).call("randomArg");
}
This is not a super clean solution but you can do this (XX is the supposed return type here):
final CountDownLatch latch = new CountDownLatch(1);
doReturn(new Answer<XX>()
{
#Override
public XX answer(InvocationOnMock invocation)
{
latch.countDown();
return someInstanceOfXX;
}
}
).when(myMock).myMethod("expectedArg");
Then, to test if the method is called, do:
try {
assertTrue(latch.await(5L, TimeUnit.SECONDS));
} catch (InterruptedException e) {
// Urgh... Failed. Deal with it and:
Thread.currentThread().interrupt();
}

Mockito: mock async method [duplicate]

This question already has answers here:
Calling callbacks with Mockito
(4 answers)
Closed 9 years ago.
I need to test this method with JUnit and Mockito
function uploadData() {
myObject.getThreadPool().execute(new Runnable() {
#Override
public void run() {
upload(arguments, callbackContext);
}
});
}
How to mock myObject to call upload(arguments, callbackContext) not in background thread ?
You'll need to do a few things here. First, replace the ThreadPool with a mock, so you have access to mock execute at all. Then use an ArgumentCaptor in a verify call to get access to the Runnable. Finally, trigger the Runnable and test the state afterwards.
#Test public void shouldUploadInBackground() {
// declare local variables
MyObject mockMyObject = Mockito.mock(MyObject.class);
ThreadPool mockThreadPool = Mockito.mock(ThreadPool.class);
ArgumentCaptor<Runnable> runnableCaptor =
ArgumentCaptor.forClass(Runnable.class);
// create the system under test
when(mockMyObject.getThreadPool()).thenReturn(mockThreadPool);
SystemUnderTest yourSystemUnderTest = createSystem(mockThreadPool);
// run the method under test
yourSystemUnderTest.uploadData();
// set the runnableCaptor to hold your callback
verify(mockThreadPool).execute(runnableCaptor.capture());
// here you can test state BEFORE the callback executes
assertFalse(yourSystemUnderTest.isDataUploaded());
// call run on the callback
runnableCaptor.getValue().run();
// here you can test state AFTER the callback executes
assertTrue(yourSystemUnderTest.isDataUploaded());
}
I think the following would work:
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
upload(arguments, callbackContext);
}).when(myObjectSpy.getThreadPool()).execute(Mockito.any(Runnable.class));
but i am not realy sure.

JUnit/Mockito test failing for bizarre reason

I have a very simple method that I am trying to unit test:
public class MyAntTask extends org.apache.tools.ant.Task {
public void execute() {
fire();
}
public void fire() {
// Do stuff
}
}
I just want to write a unit test that confirms that calling execute() always invokes fire(), so I wrote this:
#Test
public void executeCallsFire() {
//GIVEN
MyAntTask myTask = Mockito.mock(MyAntTask.class);
// Configure the mock to throw an exception if the fire() method
// is called.
Mockito.doThrow(new RuntimeException("fired")).when(myTask).fire();
// WHEN
try {
// Execute the execute() method.
myTask.execute();
// We should never get here; HOWEVER this is the fail() that's
// being executed by JUnit and causing the test to fail.
Assert.fail();
}
catch(Exception exc) {
// THEN
// The fire() method should have been called.
if(!exc.getMessage().equals("fired"))
Assert.fail();
}
}
I guess (and I'm by no means an expert) Mockito normally can't mock methods that return void, but this is a workaround. You basically say "wrap my object with a Mock that will always return a specific RuntimeException whenever a particular method is about to get executed". So, instead of fire() actually executing, Mockito just sees that its about to execute and throws an exception instead. Execution verified? Check.
Instead of passing, it fails at the first Assert.fail() just below the call to myTask.execute().
For the life of me, I can't figure out why. Here's the first 10-or-so lines of the enormous stack trace JUnit is giving me for the fail:
java.lang.AssertionError
at org.junit.Assert.fail(Assert.java:92)
at org.junit.Assert.fail(Assert.java:100)
at net.myproj.ant.tasks.MyAntTaskUnitTest.executeCallsFire(MyAntTaskUnitTest.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
Any thoughts here, ye Mockito Gurus of StackOverflow? Thanks in advance!
Because myTask is a mock, the real object isn't called at all. To call a real object, use a spy.
You can test that a method is called using verify so there's no need for the exceptions.
public void executeCallsFire() {
MyAntTask myTask = Mockito.spy(new MyAntTask());
myTask.execute();
Mockito.verify(myTask).fire();
}
Wanting to mock the object that you're testing doesn't seem right though. It's usually better to design the test so that you're verifying calls to a separate object instead.
I see here more design issue:
why do you need one line method and both of them are public?
the mocks are for simulating dependencies and not for the class under test
if you'll make fire (quite unclear name) as private. You shouldn't test private behavior of your class

Categories