Question

Is it possible in mockito to verify a method was called on a mock based on whether the mock was actually used in the unit-under-test?

For a simple example, I supply a mock factory (FooFactory) to my unit-under-test, and when Foo.create() is called, it returns a mock (Foo) to be used by certain methods in the unit-under-test. How can I verify that Foo.method() is called only if Foo.create() was called by the unit-under-test?

I'm envisioning that the code would look something like this:

@Before
public void init() {
  Foo mockFoo = mock(Foo.class);
  when(fooFactory.create()).thenReturn(mockFoo);
  test = new UnitUnderTest(fooFactory);
}

@Test
... may or may not create a foo ...

@After
public void cleanup() {
  if (verify(fooFactory).create()) {  // Here's the 'conditional verification'
    Foo mockFoo = fooFactory.create();
    verify(mockFoo).close();
  }
}

For a little more concrete example, my factory returns a Reader object that I want to ensure is closed, but not every method in the class actually constructs a Reader. I could obviously add the verification to every test where I know the Reader is needed, but that seems like a lot of duplicated effort.

Was it helpful?

Solution

Are you sure that you want to write this test?

I can see two solutions:

1) You really want to make sure that the resource gets created and closed, so try to write a test, where you can verify both method calls.

2) You want to make sure that whenever the resource is opened, it is also closed. This could be implemented as an assertion in the production code...

If you really want to go ahead with your approach, you could catch the exception that the first verify throws if the create() method hasn't been called. In the catch you just return.

Also you shouldn't do the verification in the cleanup, but in the actual test method.

OTHER TIPS

Honestly it sounds like your test is tooo complicated. It's been my experience of many projects and lots of unit testing that the best way to handle things is to ensure that each test tests one thing only. You can have as many asserts as you like, but it should be one method being called and one scenario tested. Anything mo and the test becomes too complex. Plus it makes it very hard for other developers to pick up the test at a later stage when developing the app further.

So I'd suggest breaking your test up into multiple tests, one per scenario and then see if you still need this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top