3

I am using Mockito to write my test case. I have a simple class which contains a function countPerson(boolean) which I am interested to test:

public class School {
  //School is a singleton class.

  public void countPerson(boolean includeTeacher) {
       if (includeTeacher) {
          countIncludeTeacher();
          return;
       }
       countOnlyStudents();
  }

  public void countIncludeTeacher() {...}
  public void countOnlyStudents() {...}
}

In my unit test, I want to test the countPerson(boolean) function:

public class SchoolTest{
   private School mSchool;
   @Before
   public void setUp(){
      mSchool = School.getInstance();
   }
   @Test 
   public void testCountPerson() {
       mSchool.countPerson(true);
       //How to test/verify countIncludeTeacher() is invoked once?
   }
}

How to use Mockito to check/verify countIncludeTeacher() is invoked once in my test case?

Tunaki
  • 132,869
  • 46
  • 340
  • 423
user842225
  • 5,445
  • 15
  • 69
  • 119
  • 1
    Possible duplicate of [Mockito : how to verify method was called on an object created within a method?](http://stackoverflow.com/questions/9841623/mockito-how-to-verify-method-was-called-on-an-object-created-within-a-method) – AnOldSoul Nov 12 '15 at 11:32
  • 1
    @mayooran Not technically a duplicate of that, the use-case is different here: the OP needs to verify that a different method was called on the same object. – Tunaki Nov 12 '15 at 11:34
  • @mayooran, it is not duplicated at all. Please see my code carefully, I am NOT verifying a method call on another object. If you downvoted, please revoke the downvote. – user842225 Nov 12 '15 at 11:49
  • It is because when you Mock `School` class, even by calling `mockSchool.countPerson(true);` it didn't execute that method, because you are "mocking". Try to use `Mockito.spy` – Valijon Nov 12 '15 at 11:59
  • @Valijon Exactly, and that's why it is not a duplicate of that since it does not mention spies at all. – Tunaki Nov 12 '15 at 12:01

5 Answers5

7

You will have to use a spy. The problem here is that you want to verify that a method was called on a real object, not on a mock. You can't use a mock here, since it will stub all the methods in the class, thereby stubbing also countPerson to do nothing by default.

@Test 
public void testCountPerson() {
    School school = School.getInstance();
    School spySchool = Mockito.spy(school);
    spySchool.countPerson(true);
    verify(spySchool).countIncludeTeacher();
}

However, note that you should be very careful when using spies because, unless stubbed, the real methods are gettings called. Quoting Mockito Javadoc:

Real spies should be used carefully and occasionally, for example when dealing with legacy code.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
1

If you want exactly one invocation, you can go with

verify(mSchool, times(1)).countIncludeTeacher();

I you want to check for interaction and you don't care how often it happens, do

verify(mSchool).countIncludeTeacher();
Danail Alexiev
  • 7,624
  • 3
  • 20
  • 28
0
verify(mSchool, times(1)).countIncludeTeacher();

Edit: As @Tunaki mentioned this won't work. You should use spy.

newbieee
  • 440
  • 1
  • 5
  • 17
0

You have two options.

  • Set up the School such that is has X teachers and Y students and verify that either X+Y or just X is returned. This would be my preference as mocking the class your are testing feels icky to me. The two methods should be well tested, so any errors will be caught in the tests for them.
  • Use Spy as suggested by Tunaki.
Michael Lloyd Lee mlk
  • 14,561
  • 3
  • 44
  • 81
-2

You need to do by this way

Mockito.doNothing().when(mock).countIncludeTeacher();
Valijon
  • 12,667
  • 4
  • 34
  • 67