Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito - Feeling that I don't use its full potential

When using Mockito, I only use it to mock out dependencies, i.e. my workflow looks mostly like this:

I have a class with dependencies:

public class C {
    public C (A a, B b) {
        this.a = a;
        this.b = b;
    }

    public String fooBar() {
        return a.foo() + b.bar();
    }
}

In my test class, I mock out those dependencies, and tell them which values to return when some specified methods are called:

public class CSpec {
    private A a = mock(A.class);
    private B b = mock(B.class);

    @Test
    public itShouldReturnFooBar() {
        when(a.foo()).thenReturn("foo");
        when(b.bar()).thenReturn("bar");

        C c = new C(a, b);

        assertThat(c.fooBar().isEqualTo("foobar"));
    }
}

(I hope this example is not too simple or too derived ;-)). This works fine, it allows me to test classes (here: C) in isolation. Still, I never use Mockito's verify methods or any other of its features. Is it okay / sufficient to use Mockito this way?

like image 701
helpermethod Avatar asked Feb 22 '12 10:02

helpermethod


2 Answers

Verify would be typically used to check that your C really calls the A.foo() and B.bar() methods. So you could add

verify(a).foo();
verify(b).foo();

before or after the assertThat. I don't think you need or should use them here but there are several situations where you would need that:

  • a or b does something that is not visible / reachable from c's public API (for example logging)
  • You are concerned with the order of execution
  • You want to make sure that only a.foo and b.bar methods are called, nothing else like a.foo2
  • You could use those mocks as spy's, so that call to a.foo would be then routed to the aReal.foo
like image 61
vertti Avatar answered Oct 17 '22 04:10

vertti


The verify approach is particularly useful in a Tell Don't Ask style of programming.

Consider the following version of your class C:

public class C {
  public C(A a, B b, CListener L) { ... }
  ...
  public void foobar() {
    String result = complexPrivateMethod(a, b);
    L.fooBarred(result);
  }
}

Thus, rather than just computing the result, you inform some interested party (e.g. a user interface) about the result.

To test foobar now, you'd want to verify that the listener is correctly invoked:

public class CTest {
   @Mock CListener mockListener;
   ...

   @Test itShouldTellCAboutFooBar() {
      C c = new C(stubbedA, stubbedB, mockedListener);
      ...
      verify(mockedListener).fooBarred("foobar");
   }  
}

This use of verify is typical for Test-Driven Development: See Freeman & Pryce's Growing Object-Oriented Software Guided by Tests.

Thus, if you want to use the full potential of Mockito (the question), you most of all need to adopt the corresponding design philosophy in your code.

like image 43
avandeursen Avatar answered Oct 17 '22 05:10

avandeursen