What is the best way to use Guice and JMock together?
- by Yishai
I have started using Guice to do some dependency injection on a project, primarily because I need to inject mocks (using JMock currently) a layer away from the unit test, which makes manual injection very awkward.
My question is what is the best approach for introducing a mock? What I currently have is to make a new module in the unit test that satisfies the dependencies and bind them with a provider that looks like this:
public class JMockProvider<T> implements Provider<T> {
private T mock;
public JMockProvider(T mock) {
this.mock = mock;
}
public T get() {
return mock;
}
}
Passing the mock in the constructor, so a JMock setup might look like this:
final CommunicationQueue queue = context.mock(CommunicationQueue.class);
final TransactionRollBack trans = context.mock(TransactionRollBack.class);
Injector injector = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bind(CommunicationQueue.class).toProvider(new JMockProvider<QuickBooksCommunicationQueue>(queue));
bind(TransactionRollBack.class).toProvider(new JMockProvider<TransactionRollBack>(trans));
}
});
context.checking(new Expectations() {{
oneOf(queue).retrieve(with(any(int.class)));
will(returnValue(null));
never(trans);
}});
injector.getInstance(RunResponse.class).processResponseImpl(-1);
Is there a better way? I know that AtUnit attempts to address this problem, although I'm missing how it auto-magically injects a mock that was created locally like the above, but I'm looking for either a compelling reason why AtUnit is the right answer here (other than its ability to change DI and mocking frameworks around without changing tests) or if there is a better solution to doing it by hand.