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