1

I have a factory interface B which returns objects of type A. Type A is also an interface.

I am having trouble figuring out how I can define method behavior for A.doSomething() in my mocks, because every time the factory returns a new instance of A, it needs to know how to doSomething().

This is what I have so far for mocking the factory, however A doesn't know how to doSomething().

when(B.getObject()).thenReturn(Mockito.mock(A.class));

Is there some sort of way I can define A.doSomething() for all instances of A which will be returned?

Any help is greatly appreciated.

thecatnapp
  • 11
  • 3
  • 1
    *"Is there some sort of way I can define A.doSomething() for all instances of A which will be returned?"* afaik "no". Just use `A mock = Mockito.mock(A.class); when(mock.doSomething()).thenReturn("blub"); when(B.getObject()).thenReturn(mock);`. – Tom Feb 05 '16 at 00:37
  • Factory B's getObject() method should return a new instance of A each time, not the same mock A each time. Or is this not how Mockito works? – thecatnapp Feb 05 '16 at 00:52
  • 1
    I would first wonder why you would need that during a mock. What do you want to test? – Tom Feb 05 '16 at 00:56
  • If you need `getObject()` to return a new instance each time, use [`thenAnswer()`](http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/stubbing/Answer.html) instead of `thenReturn()`. But as @Tom says, it's not clear why you would care. Maybe you need to give more test context. – David Moles Feb 05 '16 at 01:11
  • "Factory B's getObject() method should return a new instance of A each time" unless your internal logic really depends on this behavior (e.g. you are getting multiple `A`s and you need them to be different instances), you shouldn't care if the mockFactory is really returning new instance every time. Even you need, when writing your unit test, you should also know how many times your factory will be called. You can prepare appropriate number of `A` mocks to return, and do your verification accordingly afterwards – Adrian Shum Feb 05 '16 at 06:16

3 Answers3

1
A a = createA();
when(B.getObject()).thenReturn(a);

private static A createA() {
  A result = Mockito.mock(A.class);
  when(A.doSomething()).thenReturn(something);
  return result;
}

You may be tempted to try something like:

when(B.getObject()).thenReturn(createA());

but it will not work because of 'nested' mocking. More details here.

Community
  • 1
  • 1
Dragan Bozanovic
  • 23,102
  • 5
  • 43
  • 110
0

In case someone else runs into a similar situation, this is what ended up working for me after playing around with thenAnswer() as suggested in the comments.

private static A createA() {
    A a = Mockito.mock(A.class);
    when(a.doSomething()).thenReturn(...);
    return a;
}

when(B.getObject()).thenAnswer(new Answer<A>(){

            @Override
            public A answer(InvocationOnMock invocation) throws Throwable {
                A a = createA();
                return a;
            }

        });
thecatnapp
  • 11
  • 3
0

As a mock factory, your SUT normally shouldn't care about whether it is a "new instance" everytime.

Hence, what you need to do is simply:

B mockFactory = mock(B.class);
A mockA = mock(A.class);
when(mockFactory.getObject()).thenReturn(mockA);
when(mockA.doSomething()).thenReturn(123);

// Call your SUT, and then whenever the factory's getObject() is called, 
// it will return the same mockA, and when mockA.doSomething() is called,
// it will always return 123.

Of course you can use doAnswer() and return a new mock A everytime. However, you will be difficult to verify the interaction with your As.

Adrian Shum
  • 38,812
  • 10
  • 83
  • 131