Trying to define a Mockito-stub executes the mocked method. Why? - mockito

We are trying to define a UnitTest where we mock an object which I here called x for simplicity:
...
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import org.kubek2k.springockito.annotations.SpringockitoContextLoader;
import org.kubek2k.springockito.annotations.WrapWithSpy;
...
#ContextConfiguration(
loader = SpringockitoContextLoader.class,
inheritLocations = true)
public class SyncServiceIntegrationTest extends AbstractIntegrationTest {
#Autowired
#WrapWithSpy
private EventDrivenIssueDeliveryConfirmer x;
...
#Before
public void setUp() {
...
doNothing().when(x).foobar(any(Event.class));
}
...
i.e. we want our UT (not shown here) to later NOT call the method foobar on that object x.
Strange enough we get an NPE during initialization of this UT-class. The NPE is thrown by method foobar(), when the passed argument is null.
As turned out this call with argument null happens in the line doNothing()... in the setup-method which in our understanding is supposed to just define the mock-object's stubbing. But instead it evaluates the any(Event.class)-expression which apparently yields null and with that result it then calls the foobar(...)-method on x which causes the NPE.
Besides the NullPointerException we also get an error message from Mockito:
java.lang.NullPointerException: null
... <stack trace omitted for brevity>
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced or misused argument matcher detected here:
-> at ch.sst.integration.SyncServiceIntegrationTest .setUp(SyncServiceIntegrationTest.java:69)
You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
... <examples omitted for brevity>
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at ch.sst.integration.SyncServiceIntegrationTest .setUp(SyncServiceIntegrationTest.java:69)
...
Why is that so??? Why is our stubbing considered "unfinished"? What are we missing here?
Later addition:
The issue seems to have to do with the fact that class
EventDrivenIssueDeliveryConfirmer is marked with #Transactional. Removing/commenting that lets the UT succeed. But of course that's no workaround - we need that annotation.
At least this provides a hint in which direction to search. The wrapping caused by #Transactional and the wrapping done by Mockito seem to step on each other's foot here.

I have the same issue but with a totally different setup: kotlin, mockito and, of course, mockito-kotlin.
I comment on this issue because maybe somebody will come to this question with the kotlin mockito problem in the future? I sure did. Anyhow.
When not declaring a method as open in kotlin it's compiled as a final method which can't be mocked by mockito-kotlin. As a result the method gets executed which to me is kind of weird but that's what it does. It's mentioned in the mockito-kotlin github issues under https://github.com/mockito/mockito-kotlin/issues/314

Related

How to declare a constructor or extends a class of a groovy script?

I am working on a shared library for Jenkins, and I want to access some utilities methods between some classes, but not all of them, thus I have established some statements:
I would like to avoid using static methods, since it does not access pipeline steps directly, and passing the pipeline instance every call would be a pain;
I would like to avoid a singleton as well, or prefixing every method call with the util class' instance;
Since it is not supposed to be shared between all classes I would like to avoid putting every method as a file on vars/ special directory, but I would like a similar behavior;
Despite extending the class would be a anti-pattern, it would be acceptable, though I would like to avoid the verbose Java syntax for declaring the class the same name as the file, once it is implicit in groovy;
This question does solve my problem partially, although there are issues with serialization, I noted that when I use checkpoint and some build is resumed from some stage, the instance loses all extra methods.
This other question would have helped me fix the serialization issue, however the author seems the have solved the root cause of his problem using a way that is not the original question titled for.
Is there a way to extends a implicit script class in groovy without using the class NameOfFile extends SomeOtherClass { put every thing inside this block } syntax? And without working with inner-class?
Or else, is there a way to declare a constructor using the script groovy syntax analogue as the previous question?
Or even, is there a way to change the serialization behavior to install the extra methods again after unserializing?
Appendix
The script syntax works more-or-less like this:
Consider the content of file src/cicd/pipeline/SomePipeline.groovy:
package cicd.pipeline
// there is no need to wrap everything inside class SomePipeline,
// since it is implicit
def method() {
// instance method, here I can access pipeline steps freely
}
def static otherMethod() {
// static method, here it is unable to access pipeline steps
// without a instance
}
#groovy.transform.Field
def field
def call() {
// if the class is used as method it will run
this.method()
SomePipeline.otherMethod() // or simply otherMethod() should work
this.field = 'foo'
println "this instance ${this.getClass().canonicalName} should be cicd.pipeline.SomePipeline"
}
// any code other than methods or variables with #Field
// annotation will be inside a implicit run method that is
// triggered likewise main method but isn't a static one
def localVar = 'foo'
println "It will not execute on constructor since it is on run: $localVar"
println "Method: ${org.codehaus.groovy.runtime.StackTraceUtils.sanitize(new Throwable()).stackTrace[0].methodName}"
println "this instance ${this.getClass().canonicalName} should be cicd.pipeline.SomePipeline"
If I was going to use the Java verbose syntax I would have to wrap almost everything inside a class SomePipeline which is implicit in groovy, this is the script syntax I want to keep.
I realised that this.getClass().superclass.canonicalName when outside Jenkins pipeline is groovy.lang.Script and when inside pipeline is org.jenkinsci.plugins.workflow.cps.CpsScript and based on this resource I was able to elaborate the following solution:
abstract class CustomScript extends org.jenkinsci.plugins.workflow.cps.CpsScript {
public CustomScript() {
// do something here, it will always execute regardless
// serialization, and before everything
}
}
#groovy.transform.BaseScript CustomScript baseScript
That is it, worked as expected! Of course you can elaborate this solution better in order to reduce repeating and avoid inner-classes, but I will leave it for your imagination.

getting org.mockito.exceptions.misusing.InvalidUseOfMatchersException in a seemingly right code

I have a when call like this :
#Mock
private MyEventFactory myEventFactory;
#Mock
private MyEvent myEvent;
when(myEventFactory.createMyEvent(anyObject(),anyObject(),anyObject(),anyObject(),anyObject(),anyObject(),anyObject(),anyObject(),anyObject(),anyObject(),anyObject())).thenReturn(myEvent);
However I get an exception
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here:
You cannot use argument matchers outside of verification or stubbing.
MyEventFactory is an interface
What could be the issue here ?
Have you initialized the mocks? It would help to see the full code posted, but I suspect you need to call something like
MockitoAnnotations.initMocks(this);
before you run your when statement. This article shows an example: https://howtodoinjava.com/mockito/mockito-mock-initmocks/

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!

Mocking Matcher with non native class

I am trying to write a #test in Junit using mockito and powermock. I have no issue stubbing methods that have no parameters. However when I try telling mockedBank to return true no matter what is passed into latePay, I get java.lang.NullPointerException. latePay is a final method that is why I am using powermock. Any suggestions are much appreciated.
BankGenerator mockedBank = PowerMockito.mock(BankGenerator.class);
when(mockedBank.latePay(Matchers.any(MoneyCalculator.class))).thenReturn(true);
Have you added the correct annotations to your class containing the tests?
For example:
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassWithFinalMethod.class)
public class ClassContainingUnitTests {
...
}
I have used PowerMock with EasyMock in the past, and forgetting to include these annotations sometimes resulted in strange results.
For further reference, check here:
http://www.codeproject.com/Articles/806508/Using-PowerMockito-to-Mock-Final-and-Static-Method
Hope this helps.

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