20

I know you can verify the times a spied object's method was called. Can you verify the result of the method call?

Something like the following?

verify(spiedObject, didReturn(true)).doSomething();
David
  • 10,418
  • 17
  • 72
  • 122
  • 6
    @BrianRoach this question is about the value RETURNED by a spied object not the value PASSED to it – John B Jun 06 '13 at 16:42
  • **Simpy use an `Answer` class, see:** stackoverflow.com/[Spy: gather return values?](https://stackoverflow.com/q/7095871/8740349) – Top-Master Jun 01 '22 at 07:08

2 Answers2

14

To verify the number of times it was invoked, use verify(spiedObject, times(x)).doSomething().

You should NOT be verifying the value returned from the spied object. It is not the object under test so why verify what it returns. Instead verify the behavior of the object under test in response to the value returned from the spy.

Also, if you don't KNOW what value will be returned by the spied object it would be better to use a mock instead of a spy.

John B
  • 32,493
  • 6
  • 77
  • 98
  • 9
    There are times when you want to verify the return value - for example, to verify the result of a computation. Or, say, you are spying, for example, on a sensor class, and you want to verify that the sensor returns an "alert" status when it receives the type of input that causes the "alert". – luis.espinal Jul 14 '15 at 21:40
  • 1
    @luis.espinal your above description looks like testing of the spied object (verifying alert returned on alert input). This should be done in a test for the spied object not in a test for an object that uses the spied object. I would also suggest that if there is complicated behavior behind return a result of alert, you should use a stubbed method. – John B Jul 15 '15 at 10:41
  • Ah yes, you are right, I misunderstood your post. You are most definitely correct. – luis.espinal Jul 15 '15 at 14:12
  • 3
    I think that if with Mockito you can verify the values passed to a method, you should be able to verify the result too. – ejaenv Oct 15 '19 at 10:41
0

TL;DR
I am providing a template for tests where you want to verify what SpyBean method is returning. The template is using Spring Boot.

@SpringJUnitConfig(Application.class)
public class Test extends SpringBaseTest
{
    @SpyBean
    <replace_ClassToSpyOn> <replace_classToSpyOn>;

    @InjectMocks
    <replace_ClassUnderTest> <replace_classUnderTest>;

    // You might be explicit when instantiating your class under test.
    // @Before
    // public void setUp()
    // {
    //   <replace_classUnderTest> = new <replace_ClassUnderTest>(param_1, param_2, param_3);
    // }

    public static 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;
        }
    }

    @org.junit.Test
    public void test_name()
    {
        // Given
        String expString = "String that the SpyBean should return.";
        // Replace the type in the ResultCaptor bellow from String to whatever your method returns.
        final Test.ResultCaptor<String> resultCaptor = new Test.ResultCaptor<>();
        doAnswer(resultCaptor).when(<replace_classToSpyOn>).<replace_methodOnSpyBean>(param_1, param_2);

        // When
        <replace_classUnderTest>.<replace_methodUnderTest>(param_1, param_2);

        // Then
        Assert.assertEquals("Error message when values don't match.", expString, resultCaptor.getResult());
    }
}

Now that this is out of the way. There are situations where you would want to verify that your SpyBean is returning the result value. For example, there are two internal method invocations in your method under test that would produce the same value. Both get invoked but only one of them produces the wanted result.

Konstantin Grigorov
  • 1,356
  • 12
  • 20