4

Hello I would like to know what is the best approach to mock void methods for example: I have a PersonManager under the test and then I have dao that is mocked.

class PersonManager {

    PersonDao dao...

    PersonManager(PersonDao dao)...

    Preson find(String person)...

    void delete(String person)...

}

class PersonManagerTest {

    Map<String, Person> persons ..... = "person1", "person2", "person3";

    PersonDao mock...

    PersonManager manager = new PersonManager(mock);

    //easy one
    @Test public void shouldReturnExistingPerson() {
        expect(mock.find("person1").andReturn(persons.get(0));
        Person result = manager.find("person1");
        // replay and verify logic
    }

    //but what should I do here?
    @Test public void shouldDeleteExistingPerson() {
        //should I remove a person from testing Map holding test data? or what am I doing wrong
    }
}

So testing method with return was easy but how to toset void method? Thank you for suggestions, and Mcokito examples are welcomed too. }

Jarek
  • 7,425
  • 15
  • 62
  • 89

4 Answers4

6

With easy mock, you don't need to wrap void functions around expect(). You just need to do something like:

obj = createMock(...)
obj.someVoidMethod();
replay(obj);
...
verify(obj);
Amir Raminfar
  • 33,777
  • 7
  • 93
  • 123
4

It depends entirely on what you're trying to test.

In mockito, if you want to check only that the DAO delete method is called with the correct parameter, then verify is what you want.

I would suggest that this is exactly what you want since your unit test for PersonManager should not be testing PersonDao.

Alan Escreet
  • 3,499
  • 2
  • 22
  • 19
1

When deleting something, I suggest returning the object you just deleted. It makes testing much, much easier and allows doing things after you deleted (e.g. showing notice, logging, etc). I think most (all?) Java collections are doing so.

Miki
  • 7,052
  • 2
  • 29
  • 39
  • About most / all. All Java collections inherit from the same interface, so if one returns the deleted object, all do. – Sean Patrick Floyd May 10 '11 at 14:36
  • 1
    This is all true and correct, however very slightly misses the intent of the test (as I understand it). Testing if `PersonManager.delete()` returns a `Person` instance is not the same as testing if it calls `PersonDao.delete()`. – Alan Escreet May 10 '11 at 14:43
  • Again true, but then you're testing if it returns true/false, *not* that the DAO is being called with the correct parameter. – Alan Escreet May 10 '11 at 15:12
0

Mockito provides a static verify method that can verify when you call any method, even those that have void as return type. For your code sample, the following mockito code should work:

// Put this among your import statements    
import static org.mockito.Mockito.*

class PersonManagerTest {

    private PersonManager manager; // SUT

    private Map<String, Person> mockedPersons;

    private PersonDao mockDao;

    // Don't forget to setup from scratch for each test
    @Before public void setup() {
        mockDao = mock(PersonDao.class); // mockito mock method
        mockedPersons = new HashMap<String, Person>();
        for (int i=1; i<=3; i++) {
            mockedPersons.put("person"+i, mock(Person.class));
        }
        manager = new PersonManager(mockDao);
    }

    // setup dao to return a mocked person
    private void whenPersonIsAdded(int i) {
        Person personToReturn = mockedPersons.get("person"+i);
        when(mockDao.find("person"+i)).thenReturn(personToReturn);
    }

    @Test public void shouldReturnExistingPerson() {
        whenPersonIsAdded(1);
        Person expectedPerson = mockPerson;

        Person actualPerson = manager.find("person1");

        assertEquals(expectedPerson, actualPerson);
    }

    @Test public void shouldDeleteExistingPerson() {
        String expectedPersonString = "person1";

        manager.delete(expectedPersonString);

        verify(mockDao).delete(expectedPersonString);
    }
}

Hope this helps.

Spoike
  • 119,724
  • 44
  • 140
  • 158