How to execute original method in Mockito after Answer on Spy object - mockito

I would like to know is the thing in the description possible and how to do it.
I know you can call original method and then do the Answer like this:
when(presenter, "myMethod").doAnswer(<CUSTOMANSWER>)
but I would like to order them differently, first do CUSTOMANSWER and then call the original method.

For followers, it's actually possible to doAnswer and callRealMethod at the same time...
doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
invocationOnMock.callRealMethod(); // this one
return null;
}
}).when(subject).method(...);

You won't ever see when(...).doAnswer() in Mockito. Instead, you'll see either of the following, which includes the "call real method" behavior you're describing. As usual with Mockito stubbing, Mockito will select the most recent chain of calls that matches the method call and argument values in the invocation, and do each action in the chain once until the final action (which it will do for all calls afterwards.
// Normal Mockito syntax assuming "myMethod" is accessible. See caveat below.
when(presenter.myMethod()).thenAnswer(customAnswer).thenCallRealMethod();
// ...or...
doAnswer(customAnswer).doCallRealMethod().when(presenter).myMethod();
That said, there's a deficiency in the PowerMockito API that makes this difficult, because after the first doAnswer call all subsequent calls you get a normal Mockito Stubber instance rather than a PowerMockitoStubber instance. The bug 599 was misinterpreted, so for the time being you'll still have to make the cast yourself.
((PowerMockitoStubber) doAnswer(customAnswer).doCallRealMethod())
.when(presenter, "myMethod");

Related

Mockito verify doesn't match multiple stub

It seems that, when I use thenReturn like this:
when(abc.call()).thenReturn(a).thenReturn(b),
I expect:
verify(abc, times(2)).call()
instead, the method seems only get called once, I am a little confused(my test work as expected, the mock seems return the value I expected), but for the invocation times, I don't know if I am getting the wrong result, or it's a expected behavior of the Mockito?
when() is mocking the abc.call() method which has to produce a certain return type. If the method is called once, it will return the value also once, so the stubbing for method invocation is done only once hence the verify only recognizes one call.
You need to customize your function so that the stub(abc.call()) gets called more than once.
You can follow this thread for implementing multiple stubs

Mockito and Mockito.any(Map.class)

Using Mockito I got in trouble with the following:
Mockito.when(restOperationMock.exchange(
Mockito.anyString(),
Mockito.any(HttpMethod.class),
Mockito.any(HttpEntity.class),
Mockito.eq(CustomerResponse.class),
**Mockito.anyMap()**)).
thenReturn(re);
The problem was the method wasn't intercepted because I was using Mockito.any(Map.class) instead of Mockito.anyMap() and I was passing as a parameter a HashMap. What are the differences between Mockito.any(Map.class) and Mockito.anyMap()?
There is only one small difference between any(Map.class) and anyMap(): Starting with Mockito 2.0, Mockito will treat the any(Map.class) call to mean isA(Map.class) rather than ignoring the parameter entirely. (See the comment from Mockito contributor Brice on this SO answer.) Because restOperationMock.exchange takes an Object vararg, you may need anyMap to catch a case where a non-Map object is being passed, or no object at all is passed.
(I'd previously put that as a "dummy value" to return, Mockito can return an empty Map for calls to anyMap(), but can only return a null for calls to any(Map.class). If restOperationMock.exchange delegates to a real implementation during stubbing, such as if it were a spy or unmockable method (final method, method on a final class, etc), then that dummy value may be used in real code. However, that's only true for any(); anyMap() and any(Map.class) both give Mockito enough information to return a dummy Map implementation, where any() has its generics erased and only knows enough to return null.)

Mockito.when() not working

I am trying to mock a call to a protected method of one of my classes:
import com.couchbase.client.java.view.Stale; // an enum
import com.google.common.base.Optional;
public class MyClass {
public List<String> myList(Optional<Integer> arg1, Optional<Stale> arg2) {
...
}
}
The mock shall be accomplished in the following way:
// Providing types for any() does not change anything
Mockito.when(myClass.myList(Mockito.any(), Mockito.any()).thenReturn(new ArrayList());
Whenever the previous line is executed the actual myList() method is called with null values for arg1 and arg2. Why is the method called, at all? After all, I am trying to avoid any executing thereof...
As Brice mentioned, if your myList method is final, then Java skips virtual method dispatch and will call the original object (not your mock).
If you are spying on an actual class, it is expected behavior that when will call the actual object as part of the stub: after all, in the expression when(foo.bar()) Java doesn't know anything special about when and assumes that it cares about the return value) of foo.bar(), not the call itself. (I walk through the stubbing process in the "Implementation details" section of my answer here.)
This syntax is better for spies:
doReturn(new ArrayList()).when(myClass).myList(any(), any());
Because this different when method receives an object, Mockito can prepare the object to do nothing during the stubbing, which avoids any spurious calls to your myList method.
Although Jeff's answer did not show a workaround for my problem it pointed me into the right direction.
After changing the mocking behaviour to doReturn... I suddenly got an error message. This message told me that myClass is not a mock which makes sense since you can only mock (or stub?) methods of mocked or spied objects. So as Jeff's answer indicates and is explained in the documentation of mockito I created a partial mock of MyClass with
MyClass myClass = Mockito.spy(new MyClass());
With this partial mock Jeff's approach to method mocking suddenly worked (mine still does not and should therefore be avoided).
So: Thank you, Jeff!

Groovy - Correct way to implement getProperty method

I need to run some code whenever a property value is retrieved, so naturally it made sense to define the getProperty method in my class. This method will get automatically called whenever a property value is retrieved. Here's roughly what I have in my class:
class MyClass
{
def getProperty(String name)
{
// Run some code ...
return this.#"${name}"
}
}
The problem with the above method occurs when someone tries to make the following call somewhere:
MyClass.class
This call ends up in the getProperty method looking for a property named "class", however, there is not actual property named "class" so we get a MissingFieldException.
What would be the correct way to implement running code whenever a property value is retrieved and deal with these kind of situtations.
Best is not to have a getProperty method if not needed. If you need one and you want to fall back on standard Groovy logic, then you can use return getMetaClass().getProperty(this, property), as can be found in GroovyObjectSupport. This will cover more than just fields.
This seems to be a common problem with this method. Map has the same issue. The developers of groovy got around the problem with Map by saying you need to use getClass() directly.

Mockito isNotNull passes null

Thanks in advance for the help -
I am new to mockito but have spent the last day looking at examples and the documentation but haven't been able to find a solution to my problem, so hopefully this is not too dumb of a question.
I want to verify that deleteLogs() calls deleteLog(Path) NUM_LOGS_TO_DELETE number of times, per path marked for delete. I don't care what the path is in the mock (since I don't want to go to the file system, cluster, etc. for the test) so I verify that deleteLog was called NUM_LOGS_TO_DELETE times with any non-null Path as a parameter. When I step through the execution however, deleteLog gets passed a null argument - this results in a NullPointerException (based on the behavior of the code I inherited).
Maybe I am doing something wrong, but verify and the use of isNotNull seems pretty straight forward...here is my code:
MonitoringController mockController = mock(MonitoringController.class);
// Call the function whose behavior I want to verify
mockController.deleteLogs();
// Verify that mockController called deleteLog the appropriate number of times
verify(mockController, Mockito.times(NUM_LOGS_TO_DELETE)).deleteLog(isNotNull(Path.class));
Thanks again
I've never used isNotNull for arguments so I can't really say what's going wrong with you code - I always use an ArgumentCaptor. Basically you tell it what type of arguments to look for, it captures them, and then after the call you can assert the values you were looking for. Give the below code a try:
ArgumentCaptor<Path> pathCaptor = ArgumentCaptor.forClass(Path.class);
verify(mockController, Mockito.times(NUM_LOGS_TO_DELETE)).deleteLog(pathCaptor.capture());
for (Path path : pathCaptor.getAllValues()) {
assertNotNull(path);
}
As it turns out, isNotNull is a method that returns null, and that's deliberate. Mockito matchers work via side effects, so it's more-or-less expected for all matchers to return dummy values like null or 0 and instead record their expectations on a stack within the Mockito framework.
The unexpected part of this is that your MonitoringController.deleteLog is actually calling your code, rather than calling Mockito's verification code. Typically this happens because deleteLog is final: Mockito works through subclasses (actually dynamic proxies), and because final prohibits subclassing, the compiler basically skips the virtual method lookup and inlines a call directly to the implementation instead of Mockito's mock. Double-check that methods you're trying to stub or verify are not final, because you're counting on them not behaving as final in your test.
It's almost never correct to call a method on a mock directly in your test; if this is a MonitoringControllerTest, you should be using a real MonitoringController and mocking its dependencies. I hope your mockController.deleteLogs() is just meant to stand in for your actual test code, where you exercise some other component that depends on and interacts with MonitoringController.
Most tests don't need mocking at all. Let's say you have this class:
class MonitoringController {
private List<Log> logs = new ArrayList<>();
public void deleteLogs() {
logs.clear();
}
public int getLogCount() {
return logs.size();
}
}
Then this would be a valid test that doesn't use Mockito:
#Test public void deleteLogsShouldReturnZeroLogCount() {
MonitoringController controllerUnderTest = new MonitoringController();
controllerUnderTest.logSomeStuff(); // presumably you've tested elsewhere
// that this works
controllerUnderTest.deleteLogs();
assertEquals(0, controllerUnderTest.getLogCount());
}
But your monitoring controller could also look like this:
class MonitoringController {
private final LogRepository logRepository;
public MonitoringController(LogRepository logRepository) {
// By passing in your dependency, you have made the creator of your class
// responsible. This is called "Inversion-of-Control" (IoC), and is a key
// tenet of dependency injection.
this.logRepository = logRepository;
}
public void deleteLogs() {
logRepository.delete(RecordMatcher.ALL);
}
public int getLogCount() {
return logRepository.count(RecordMatcher.ALL);
}
}
Suddenly it may not be so easy to test your code, because it doesn't keep state of its own. To use the same test as the above one, you would need a working LogRepository. You could write a FakeLogRepository that keeps things in memory, which is a great strategy, or you could use Mockito to make a mock for you:
#Test public void deleteLogsShouldCallRepositoryDelete() {
LogRepository mockLogRepository = Mockito.mock(LogRepository.class);
MonitoringController controllerUnderTest =
new MonitoringController(mockLogRepository);
controllerUnderTest.deleteLogs();
// Now you can check that your REAL MonitoringController calls
// the right method on your MOCK dependency.
Mockito.verify(mockLogRepository).delete(Mockito.eq(RecordMatcher.ALL));
}
This shows some of the benefits and limitations of Mockito:
You don't need the implementation to keep state any more. You don't even need getLogCount to exist.
You can also skip creating the logs, because you're testing the interaction, not the state.
You're more tightly-bound to the implementation of MonitoringController: You can't simply test that it's holding to its general contract.
Mockito can stub individual interactions, but getting them consistent is hard. If you want your LogRepository.count to return 2 until you call delete, then return 0, that would be difficult to express in Mockito. This is why it may make sense to write fake implementations to represent stateful objects and leave Mockito mocks for stateless service interfaces.

Resources