Mockito + Spy: How to gather return values

21,465

Solution 1

First thing, you should be passing spy in as the constructor argument.

That aside, here's how you could do it.

public class ResultCaptor<T> implements Answer {
    private T result = null;
    public T getResult() {
        return result;
    }

    @Override
    public T answer(InvocationOnMock invocationOnMock) throws Throwable {
        result = (T) invocationOnMock.callRealMethod();
        return result;
    }
}

Intended usage:

RealFactory factory     = new RealFactory();
RealFactory spy         = spy(factory);
TestedClass testedClass = new TestedClass(spy);

// At this point I would like to get a reference to the object created
// and returned by the factory.


// let's capture the return values from spy.create()
ResultCaptor<RealThing> resultCaptor = new ResultCaptor<>();
doAnswer(resultCaptor).when(spy).create();

// do something that will trigger a call to the factory
testedClass.doSomething();

// validate the return object
assertThat(resultCaptor.getResult())
        .isNotNull()
        .isInstanceOf(RealThing.class);

Solution 2

The standard mocking approach would be to:

  1. Pre-create the object you want the factory to return in the test case
  2. Create a mock (or spy) of the factory
  3. Prescribe the mock factory to return your pre-created object.

If you really want to have the RealFactory create the object on the fly, you can subclass it and override the factory method to call super.create(...), then save the reference to a field accessible by the test class, and then return the created object.

Share:
21,465
Marc-Christian Schulze
Author by

Marc-Christian Schulze

Updated on September 05, 2020

Comments

  • Marc-Christian Schulze
    Marc-Christian Schulze almost 4 years

    I got a class using a factory for creating some object. In my unit test I would like to access the return value of the factory. Since the factory is directly passed to the class and no getter for the created object is provided I need to intercept returning the object from the factory.

    RealFactory factory     = new RealFactory();
    RealFactory spy         = spy(factory);
    TestedClass testedClass = new TestedClass(factory);
    
    // At this point I would like to get a reference to the object created
    // and returned by the factory.
    

    Is there a possibility to access the return value of the factory? Probably using the spy?
    The only way I can see is to mock the factory create method.

  • BetaRide
    BetaRide over 7 years
    Thanks for sharing. IMHO: This should be the accepted answer.
  • nahzor
    nahzor over 5 years
    Does this return a copy of the result or the same instance?
  • Jeff Fairley
    Jeff Fairley over 5 years
    it'll return the same instance
  • timon_the_destroyer
    timon_the_destroyer over 4 years
    Thanks Jeff, this was really helpful
  • Ev0oD
    Ev0oD over 3 years
    This seems like something I'd expect to be part of Mockito. It works, but maybe it's a bad design if we have to test like this? spy() doc hinted me in this direction. Anyone has any ideas?