I'm playing around with some of our existing Mockito-based Java tests to try and see if we can write them better using Spock. I'm a little unfamiliar with Groovy, so this could just be a Groovy question, but nevertheless, here goes:
I have the following method under test:
private void performAction(final T bar, final Foo foo) {
factory.getBlob().doWork(new Work() {
@Override
public void execute(Connection connection) throws SQLException {
// does some stuff with bar, foo and connection
}
});
}
I would like to mock out factory.getBlob() so that it responds to doWork(Work) by simply calling Work.execute(...).
The existing Mockito based test looks like this:
@Mock Factory factory;
@Mock Blob blob;
...
when(factory.getBlob()).thenReturn(blob);
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
((Work)invocation.getArguments()[0]).execute(mock(Connection.class));
return null;
}
}).when(blob).doWork(any(Work.class));
I tried to write it like this, which would be a very nice way to prove some Spock joy:
Factory factory = Mock()
Blob blob = Mock()
...
factory.getBlob() >> session
blob.doWork(_ as Work) >> {w -> w.execute(Mock(Connection))}
Unfortunately, this fails to match, since it seems that doWork is getting an ArrayList with a single entry passed to it, not a Work. I tried:
Factory factory = Mock()
Blob blob = Mock()
...
factory.getBlob() >> session
blob.doWork(_) >> {w -> w[0].execute(Mock(Connection))}
This now matches and executes, but I get an NPE in execute, because bar and foo are not set. I guess Mockito is doing some cleverness with the scoped finals and the stack which Spock isn't. How can I make this work? Furthermore, how is doWork being called with an ArrayList?
Thanks!