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.
Related
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.
When I write unit tests for business code, I need to mock asynchronous thread calls and return a simulated result to save in the database. I don't know how to write unit test code for this method.
The tested code is as follows:
public void doWork(){
ExecutorService executor = Executors.newSingleThreadExecutor();
FutureTask<TestVO> futureResult = null;
futureResult = new FutureTask<TestVO>(new Callable<TestVO>() {
public TestVO call() {
return testService.scan(_scan_params, finalProcess, _ywid, _logPath);
}
});
executor.execute(futureResult);
TestVO testVO = futureResult.get(0, TimeUnit.SECONDS);
TestRepository.save(testVO);
}
The method that needs to be mocked is as follows:
#Async("taskAccStepExecutor")
public TestVO scan(String params, String process, String ywid, String LogPath) {
......
return testVO;
}
I used testng/mokito as a testing framework in my project.
My expectation is to simulate an asynchronous thread and return a custom testVO. This problem has troubled me for several days and I hope to get your help.
Working on the assumption that the class that defines the doWork() method (let's call that class "Worker") gets the "testService" injected somehow and you have control over how that gets injected.
In that case, it would likely suffice if you create a Worker with a mocked testService in your unit test. Add when(testService.scan(anyString(), anyString(), anyString(), anyString()).thenReturn(new TestVO()) to mock what you are expecting from the service.
Then call the doWork method as that seems to be the method that you want to test.
Then verify that the scan method was called: verify(testService).scan(anyString(), anyString(), anyString(), anyString()).
Maybe also validate that the TestVO object was saved to your database.
public void makeLoginRequest(){
view.log(sessionHandler.getEncodedCredentials());
Call loginCall = apiService.getLoginInfo("application/json", "application/json"
, "SPT", "Android", sessionHandler.getEncodedCredentials());
loginCall.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
handleLoginResponse(response);
}
#Override
public void onFailure(Call<User> call, Throwable t) {
handleLoginFailure(t);
}
});
}
I'm trying to test this method with JUnit and Mockito. This method belongs in a presenter class. In order to test this I run
presenter.makeLoginRequest(); then when the onResponse is called
I use verify(presenter).handleLoginResponse(response); which never gets called. The issue is that it will continue to run everything in handleLoginResponse(response);. I don't want to execute whats in this method, but only need to verify that this method gets called.
How can I ignore the method execution, or what is the best way to test this?
There 2 ways of doing this:
Make your presenter become a mock object
presenter = mock<Presenter>()
Add this to your test
doNothing().when(presenter).handleLoginResponse(any());
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();
}
I am writing a Api that executes HTTP Request on a worker thread then call a method of a Callback-Handler when finish.
public class GriklyClient <E,T>{
private final IHttpRequest<E,T> request;
private final ResponseListener<T> response;
protected GriklyClient (IHttpRequest<E,T> request,ResponseListener<T> response)
{
this.request = request;
this.response = response;
}
/**
* Dispatch a thread to process
* HTTP Request.
*/
public void execute ()
{
Runnable thread = new Runnable()
{
public void run()
{
T result = (T) request.execute ();
response.response(result);
}
};
new Thread(thread).start();
}//end execute method
}
This is how a call to the ApI looks like:
Grikly grikly = new Grikly(developerKey);
grikly.addValidUserCredential(email,password);
grikly.fetchUser(1, new ResponseListener<User>() {
public void response(User result) {
// TODO Auto-generated method stub
System.out.println(result);
}
});
The problem I am having is Unit Testing. The Callback Handler is not being called in my Unit Test thus all my Test always pass even when they should fail.
private Grikly grikly = new Grikly (developerKey);
#Test
public void fetchUser ()
{
grikly.fetchUser(1, new ResponseListener<User>() {
public void response(User result) {
Assert.assertNotNull(result);
}
});
}//end fetchUser Test
How can I write a Unit test to test this Api?
Well, I guess your problem here is because your method fetchUser is an asynchonous method rather than a synchonous one which will not return until it have done its job.
So, the calling of grikly.fetchUser(... will return immediately(so does the test method fetchUser() w/o any sign of failure or success), while the 'lonely' thread you create in GriklyClient will keep running and finish its job by calling the callback method response in your new ResponseListener<User> and of course, nobody cares at that time.
IMO, either a CountdownLatch or a more general ReentrantLock with its Condition buddy can save your day. And tutorials talking about these two tools can be easily found using Google. Good luck with that.
EDIT:
On a second thought, if you wanna test the result that got passed to the callback method, it might be necessary to pass(or publish) it from the new thread you create to the test main thread(by save it to a lock guarded or volatile decorated field) and test it in the #Test annotated method, which in your case is the fetchUser().