Hot questions for Using Mockito in groovy
Question:
I am writing my Junit test cases for Groovy using Mockito jar, but it is giving me following exception:
java.lang.NoSuchMethodError: org.mockito.internal.runners.RunnerFactory.createStrict(Ljava/lang/Class;)Lorg/mockito/internal/runners/InternalRunner; at org.mockito.junit.MockitoJUnitRunner.<init>(MockitoJUnitRunner.java:152) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104) at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86) at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59) at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26) at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59) at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createUnfilteredTest(JUnit4TestLoader.java:84) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:70) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:43) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:444) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Below is the jar list that I have:
cglib-nodep-2.2.2 javassist-3.19.0-GA junit-4.12 mockito-all-1.10.19 objenesis-2.5 powermock-mockito-1.6.2-full
Below is my code. I have added necessary imports:
package test.service import org.junit.Test import org.junit.runner.RunWith import org.mockito.InjectMocks import org.mockito.Mock import org.mockito.junit.MockitoJUnitRunner import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) class SyncImplTest { @InjectMocks SyncThreatImpl fixture; @Mock RpcConfigurationLoader rpcConfigurationLoader @Test public void testRpcConfig(){ RpcApiInfo rpcApiInfo = new RpcApiInfo(); when(rpcConfigurationLoader.loadConfiguration()).thenReturn(rpcApiInfo) } }
Answer:
For some reason, your test suite, tries to load the MockitoJunitRunner
from the org.mockito.junit
contained in the Mockito versions >= 2. O. In that version, the line:
at org.mockito.junit.MockitoJUnitRunner.<init>(MockitoJUnitRunner.java:152)
is doing this:
public MockitoJUnitRunner(Class<?> klass) throws InvocationTargetException { //by default, StrictRunner is used. We can change that potentially based on feedback from users this(new StrictRunner(new RunnerFactory().createStrict(klass), klass)); }
and the RunnerFactory that is loaded here is from version 1.x as createStrict
has been introduced in Mockito 2.x.
So go through the pom dependency tree and to find what artifact implicitly add the Mockito 2.x dependency to your project and exclude it.
Alternatively.. as a workaround, instead of the @RunWith(MockitoJUnitRunner.class)
you can use:
@Before public void init() { MockitoAnnotations.initMocks(this); }
You can also check out this Mockito cheat sheet to keep all the standards at hand.
Question:
Groovy appears to be messing up my stubbing. The following test passes:
MockitoStubTest2.java:
public class MockitoStubTest2 { @Test public void testStubbing() { MyInterface myInterface = mock(MyInterface.class); when(myInterface.someMethod(isA(MyClass.class))).thenReturn("foobar"); assertEquals("foobar", myInterface.someMethod(new MyClass())); } private interface MyInterface { String someMethod(MyClass arg); String someMethod(String arg); } private static class MyClass {} }
However, this one fails with groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method ...#someMethod
:
MockitoStubTest3.groovy:
public class MockitoStubTest3 { @Test public void testStubbing() { MyInterface myInterface = mock(MyInterface.class); when(myInterface.someMethod(isA(MyClass.class))).thenReturn("foobar"); assertEquals("foobar", myInterface.someMethod(new MyClass())); } private interface MyInterface { String someMethod(MyClass arg); String someMethod(String arg); } private static class MyClass {} }
The only difference is that one is run with Java and the other with Groovy.
How can I make it so Mockito will successfully stub an overloaded method in Groovy? This is a trivial example but I have an actual use case I need to test.
Answer:
Ok I figured it out right after I posted this question... even though I've been fighting with this all day.
The problem is that the Mockito matcher methods return null
but Groovy for some reason screws up the type-cast. So you need to do the type-cast manually in order for it to find the correct method to stub. The following works:
MockitoStubTest3.groovy:
public class MockitoStubTest3 { @Test public void testStubbing() { MyInterface myInterface = mock(MyInterface.class); when(myInterface.someMethod(isA(MyClass.class) as MyClass)).thenReturn("foobar"); assertEquals("foobar", myInterface.someMethod(new MyClass())); } private interface MyInterface { String someMethod(MyClass arg); String someMethod(String arg); } private static class MyClass {} }
I got the answer from this similar question: Mockito any matcher not working for doAnswer with overloaded method
Question:
I got two methods:
protected List<CustomObject> getSortedOrderItems() { List<CustomObject> internalList = new ArrayList<>(); //some operations return internalList; } public CustomObject getIdentifire() { CustomObject correctIdentifire = null; List<CustomObject> items = getSortedOrderItems(); //some opearations on items return correctIdentifire; }
For my Junit tests I need to mock
List<CustomObject> items = getSortedItems();
as a list of my customObjects
I dont know how to start it. I am aware how to use Mockito in normal cases but never done something like this. Any help?
Answer:
In groovy you can simply use meta-programming to mock anything directly:
class SomeClass { protected List<CustomObject> getSortedOrderItems() { List<CustomObject> internalList = new ArrayList<>(); //some operations return internalList; } } @groovy.transform.TupleConstructor class CustomObject { int a } // test setup: SomeClass.metaClass.getSortedOrderItems = {-> [ new CustomObject(1), new CustomObject(2) ] } // test assert [ 1, 2 ] == new SomeClass().sortedOrderItems*.a