Search code examples
mockitorx-javajunit4

rx java and Mockito not working


I am getting the following error when i do the below:

org.mockito.exceptions.misusing.MissingMethodInvocationException: when() requires an argument which has to be 'a method call on a mock'. For example: when(mock.getArticles()).thenReturn(articles);

How do i mock a rx java object?

     <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>2.11.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.reactivex.rxjava2</groupId>
        <artifactId>rxjava</artifactId>
        <version>2.1.7</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>


@RunWith(MockitoJUnitRunner.class)
public class UnitTestJunit4 {


@Mock
Session session;

@BeforeClass
public static void runOnceBeforeClass() {
    System.out.println("@BeforeClass - runOnceBeforeClass");
}

// Run once, e.g close connection, cleanup
@AfterClass
public static void runOnceAfterClass() {
    System.out.println("@AfterClass - runOnceAfterClass");
}

// Should rename to @BeforeTestMethod
// e.g. Creating an similar object and share for all @Test
@Before
public void runBeforeTestMethod() {

    System.out.println("@Before - runBeforeTestMethod");

    MockitoAnnotations.initMocks(this);
    when( session.getSession("a","b","c","d") )
      .thenReturn( Single.error( new Exception() ) );
}

// Should rename to @AfterTestMethod
@After
public void runAfterTestMethod() {
    System.out.println("@After - runAfterTestMethod");
}

@Test
public void test_method_1() {
    System.out.println("@Test - test_method_1");
}

@Test
public void test_method_2() {
    System.out.println("@Test - test_method_2");
}
}


public class Session {

public static Single<Session> getSession(String a, String b, 
  String c, String d) {
  return Single.<SessionObject>create(emitter -> { 
   emitter.onSuccess(new SessionObject());
  }
}

Session class above which i am trying to Mock.


Solution

  • You need to use PowerMockito because getSession() method inside Session class is a static method. You cannot mock a static method using Mockito.

    You can use PowerMockito like this,

    1. Add PowerMockito in Gradle

      dependencies {
          testImplementation "org.powermock:powermock-module-junit4:1.6.6"
          testImplementation "org.powermock:powermock-module-junit4-rule:1.6.6"
          testImplementation "org.powermock:powermock-api-mockito2:1.7.0"
          testImplementation "org.powermock:powermock-classloading-xstream:1.6.6"
      }
      
    2. Add this line above the class

      @PrepareForTest({Session.class})
      
    3. Then write a test method like below,

      @Test
      public void testMethod() {
          PowerMockito.mockStatic(Session.class);
          PowerMockito.when(Session.getSession("a","b","c","d"))
             .thenReturn(Single.error(new Exception()));
      }
      

    Hope this answer helps.