Let me try first a quick answer, then we can iterate over details if you'd
like.
The use of Modules.override() here is what gives the ability to mock a set
of components that effectively represent interfaces to those components from
a system. For example, if you have something like:
class MakesRpcCalls {
@Inject MakesRpcCalls(
RpcInterface rpcInterface) {
...
}
RpcResponse makeRpc(RpcRequest rpcRequest) {
... do some stuff
return rpcInterface.call(rpcRequest);
}
}
You might want to mock RpcInterface in your test.
Imagine the module that binds this interface in production looks like:
public class RealRpcInterfaceModule extends AbstractModule {
@Override protected void configure() {
bind(RpcInterface.class).to(RealBackendServiceInterface.class);
...
}
}
And your application module might then install it:
public class ApplicationModule extends AbstractModule {
@Override protected void configure() {
install(new RealRpcInterfaceModule());
....
}
}
And your main() method might look like:
public static void main(String[] args) {
Injector injector = Guice.createInjector(new ApplicationModule());
Server server = injector.getInstance(Server.class);
server.runForever();
}
In an integration test, you'd want to be able to do something like start
this server pointing at a mock rpc backend. One way to do this is to add
another method:
public static void main(String[] args) {
// imagine 'EmptyModule' is one with no bindings. thus, by default,
// don't override any bindings within 'ApplicationModule'
programmaticMain(args, new EmptyModule());
}
/**
* Accepts the args from the command line and an {@code overrideModule},
the
* bindings in which are used to override bindings in the {@link
ApplicationModule}.
*/
public static void programmaticMain(String[] args, Module overrideModule) {
Module moduleToUse = Modules.override(new
ApplicationModule)).with(overrideModule);
Injector injector = Guice.createInjector(moduleTouse);
Server server = injector.getInstance(Server.class);
server.runForever();
}
In your integration test, you'd then start a server with:
Server.programmaticMain(<args>, new AbstractModule() {
@Override protected void configure() {
bind(RpcInterface.class).to(MockedOutRpcInterface.class);
}
}
Of course many variations on this theme exist, but the gist of overriding
production bindings remains the same.
Fred
On Thu, Aug 18, 2011 at 12:13 PM, Nathandelane <[email protected]>wrote:
> For a long time I have been working on a series of automated tests
> that rely on the creation of mocks through a service lookup utility
> (like Spring framework's), which in some ways resembles a dependency
> injection framework and is used like a DI framework, but it doesn't
> quite work the same way, and it has some intricacies that make it less
> reliable for DI in my opinion. Recently I've been trying to implement
> the usage of Guice in place of this service lookup utility, and I've
> been running into a possible issue that I can't seem to figure out. I
> however suppose that I must be missing something in relation to Guice.
>
> Essentially there are cases when we mock portions of a system and set
> them up in advance of running that system. Our service lookup utility
> in this sense seems to be global. In Guice however there seems to be a
> requirement of concrete implementations of AbstractModule or more
> correctly the Module interface. It seems to me that all of the
> examples provided use those implementations explicitly right before
> requesting an instance of an interface in question. If this is the
> case, then how would I implement my integration tests using Guice to
> mock certain portions of a system in advance of calling that system,
> and ensure that my mocks (in a Module implementation) get used? There
> isn't any way to do this is there? Because Guice isn't global, or
> rather the bindings aren't global to the test application or
> application under test, rather they are local.
>
> This is probably a special situation. Can anybody please help me
> clarify this point?
>
> Thanks.
>
> Nathan Lane
>
> --
> You received this message because you are subscribed to the Google Groups
> "google-guice" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/google-guice?hl=en.
>
>
--
You received this message because you are subscribed to the Google Groups
"google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-guice?hl=en.