Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I generate a spy for an interface with Mockito without implementing a stub class?

So I have the following interface:

public interface IFragmentOrchestrator {
    void replaceFragment(Fragment newFragment, AppAddress address);
}

How can I create a spy with mockito that allows me to hook ArgumentCaptor-objects to calls to replaceFragment()?

I tried

    IFragmentOrchestrator orchestrator = spy(mock(IFragmentOrchestrator.class));

But mockito complains with "Mockito can only mock visible & non-final classes."

The only solution I've come up with so far is to implement an actual mock of the interface before I create the spy. But that kind of defeats the purpose of a mocking framework:

public static class EmptyFragmentOrchestrator implements IFragmentOrchestrator {
    @Override
    public void replaceFragment(Fragment newFragment, AppAddress address) {

    }
}

public IFragmentOrchestrator getSpyObject() {
    return spy(new EmptyFragmentOrchestrator());
}

Am I missing something fundamental? I've been looking through the docs without finding anything (but I may be blind).

like image 987
Nilzor Avatar asked Oct 20 '22 01:10

Nilzor


1 Answers

Spying is when you want to overlay stubbing over an existing implementation. Here you have a bare interface, so it looks like you only need mock:

public class MyTest {
  @Captor private ArgumentCaptor<Fragment> fragmentCaptor;
  @Captor private ArgumentCaptor<AppAddress> addressCaptor;

  @Before
  public void setup() {
    MockitoAnnotations.initMocks(this);
  }

  @Test
  public void testThing() {
    IFragmentOrchestrator orchestrator = mock(IFragmentOrchestrator.class);

    // Now call some code which should interact with orchestrator 
    // TODO

    verify(orchestrator).replaceFragment(fragmentCaptor.capture(), addressCaptor.capture());

    // Now look at the captors
    // TODO
  }
}

If, on the other hand, you really are trying to spy on an implementation, then you should do that:

IFragmentOrchestrator orchestrator = spy(new IFragmentOrchestratorImpl());

This will call the actual methods on IFragmentOrchestratorImpl, but still allow interception with verify.

like image 142
Graham Avatar answered Oct 27 '22 09:10

Graham