32

I am facing an issue with Mockito junit testing. I am new to it and am a bit confused with the problem I am facing. Any help on this would be appreciated.

class Activity{

    public void firstMethod(){

      String str = secondMethod();
   }

    public String secondMethod(){
      String str = null;

      /*  some Code */

      return str;
   }
}

Getting exception :

*org.mockito.exceptions.misusing.NotAMockException: 
 Argument passed to when() is not a mock!*

in the below code

class ActivityTest(){

  Activity act;

  @Before
  public void setup(){
     act = new Activity();
  }

  @Test
  public void testFirstMethod(){

      Mockito.doReturn(Mockito.anyString()).when(act).secondMethod();
      act.firstMethod();
      verify(act).secondMethod();
  }
} 

I am aware that activity is not a mock but I am not sure for a way around this as secondMethod() is a method in the same class. I need to write rule for secondMethod() as I have already done its Unit Testing. The definition of secondMethod() consists has external dependencies. Should I be mocking the external dependencies present in secondMethod() and writing rules for them rather than rule for secondMethod()?

I found this post: Mockito Spy'ing on the object being unit tested However separating the secondMethod() into a different class does not make sense. My method is related to this class. Creating a different class for testing does not seem right to me. Even mocking the actual class using spy() is not the most correct way as already explained in the post.

I don't think I should be creating a mock of the Activity class as that is the class I am testing. I would really appreciate help and insights into this.

Mureinik
  • 297,002
  • 52
  • 306
  • 350
alwaysAStudent
  • 2,110
  • 4
  • 24
  • 47
  • 1
    You should not _mock_ away methods of the class under test. And you are right - you should not mock away the class itself. Instead mocking is designed for replacing all collaborators of the class under test. So if your class depends on other classes whose instances are used in your methods, then simply mock away those collaborators. – Seelenvirtuose Apr 13 '15 at 18:06
  • 1
    Exception is pretty clear, act is not a mock so no when() on it. Some [doc](https://github.com/mockito/mockito/wiki/FAQ) you should read IMHO –  Apr 13 '15 at 18:11

3 Answers3

60

As you noted, act is not a mock, and therefore you cannot record behavior on it. You could use Mockito.spy to, well, spy (or partially mock) the act object so that you only record the behavior of secondMethod and execute the actual code for firstMethod.

Note, however, that matchers can't be used in doReturn calls regardles of how you're mocking or spying your object. A return value must be a concrete object.

class ActivityTest() {

  Activity act;

  @Before
  public void setup(){
     act = Mockito.spy(new Activity()); // Here!
  }

  @Test
  public void testFirstMethod(){

      Mockito.doReturn("someString").when(act).secondMethod();
      act.firstMethod();
      verify(act).secondMethod();
  }
} 

A slightly more elegant syntax allows you to use annotations instead of explicitly calling Mockito.spy, but it's a matter of taste really:

@RunWith(MockitoJUnitRunner.class)
class ActivityTest() {

  @Spy
  Activity act = new Activity();

  @Test
  public void testFirstMethod(){

      Mockito.doReturn("someString").when(act).secondMethod();
      act.firstMethod();
      verify(act).secondMethod();
  }
} 
Mureinik
  • 297,002
  • 52
  • 306
  • 350
0

Here are some hints:

  1. Mock the Activity.
  2. Tweak the behavior of secondMethod with when / then / doReturn
  3. Use doCallRealMethod when firstMethod is invoked.

Hope it helps.

Pavan Kumar
  • 4,182
  • 1
  • 30
  • 45
0

There is no reason to mock anything in this example. Since there are no dependencies and both methods are public, you can test them directly.

public class ActivityTest() {

    private Activity act = new Activity();

    @Test
    public void testSecondMethod(){
        assertEquals("expected-value", act.secondMethod());
    }

    @Test
    public void testFirstMethod() {
        act.firstMethod();
        // success if no exception occurs
    }
} 

Since firstMethod does not have any detectable effect on the Act instance, nor on any dependency (since there are none) you can simply call the method and be satisfied if no exception is thrown. One could also reason that such a method should not be tested at all.

I assume the example given is a simplification of a class where calling firstMethod actually does have side effects, who knows...

Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60