0

I have a class where I want a method stubbed out, but I want to see what argument was passed to that stubbed method. However, I won't be invoking the method directly in the test, but instead invoking something that will eventually call it. So far, examples I've found for verifying arguments is only for methods that are directly invoked.

Here's an example that illustrates the problem:

public class FooTest
{
    @Test
    public void testFoo()
    {
        Foo foo = mock(Foo.class);
        when(foo.mockableMethod(anyString())).thenReturn("dummy");

        foo.parentMethod(true);

        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
        verify(foo).mockableMethod(captor.capture());
        assertEquals("foo", captor.getValue());
    }

    class Foo
    {
        public void parentMethod(boolean isFoo)
        {
            mockableMethod(isFoo ? "foo" : "bar");
        }

        protected String mockableMethod(String passedArgument)
        {
            // Only returning for brevity; assume it does a lot more.
            return passedArgument;
        }
    }
}

This yields the following error:

junit.framework.AssertionFailedError:
Wanted but not invoked:
foo.mockableMethod(<Capturing argument>);
-> at FooTest.testFoo(FooTest.java:32)

However, there were other interactions with this mock:
foo.parentMethod("foo");
-> at FooTest.testFoo(FooTest.java:29)

Is this even possible? This setup works just fine if I verify parentMethod instead of mockableMethod, but that's not very useful for me. In this example, I specifically want to make sure that the stubbed method mockableMethod is called with "foo" if parentMethod is called with true.

The only alternative I can think of is doing something like this within testFoo:

when(foo.mockableMethod("foo")).thenReturn("dummy");

... but I'm not sure how to catch the case where an argument other than "foo" is sent to it. thenThrow and fail on that? Suggestions welcome!

Depressio
  • 1,329
  • 2
  • 20
  • 39

1 Answers1

0

spy can stub methods just like mock can, and switching to spy fixes the issue:

Foo foo = spy(new Foo());

The rest of the code stays the same. However, in my actual code, I need to use doReturn before when because I didn't want it invoked:

doReturn("dummy").when(foo).mockableMethod(anyString());

(courtesy of comments on the original question)

Depressio
  • 1,329
  • 2
  • 20
  • 39