Reputation: 701
I am now using Guice for JUnit test for JSF web application. Suppose I have several classes:
class ServiceA
{
@Inject
ServiceB serviceB;
//do something using serviceB
...
}
interface ServiceB
{
//APIs in ServiceB
...
}
class ServiceBImpl implements ServiceB
{
@Inject
ServiceC serviceC;
//do something using serviceC
...
}
interface ServiceC
{
//APIs in ServiceC
...
}
class ServiceCImpl implements ServiceC
{
//do something
...
}
Now I use Guice to build a module for ServiceA. My module would look like the following
class ServiceAModule implements Module
{
@Override
public void configure(Binder binder) {
binder.bind(ServiceB.class).to(ServiceBImpl.class);
}
}
And in my JUnit test class, I use Guice to create Injection, which looks like :
public ServiceATest
{
ServiceA serviceA;
@Before
public void before()
{
Injector injector = Guice.createInjector(new ServiceAModule());
serviceA = injector.getInstance(ServiceA.class);
}
//do the test
...
}
Now the problem is the ServiceATest knows nothing about "ServiceC", and it will not be injected into ServiceB.
Of course I can build another module to introduce ServiceC's injection in ServiceB. But this surely break the code layering. What if ServiceC is developed by another person and I know nothing about ServiceC? this should not be a good solution.
Is it possbile for Guice to handle such multi-layered injection?
Upvotes: 0
Views: 623
Reputation: 28991
You should not do multi-layered injection unless you are doing an integration test.
In a unit test ServiceATest you should inject ServiceB mock and don't care about ServiceC and guice modules. You could just use mockito's @InjectMocks instead of Guice.
If you are doing an integration test, then you should decide which components are involved in a particular test. All components which are outside of the test scope you should mock, probably you would use additional ad-hock MockModule right inside the test case to bind mocked dependencies.
BTW, instead of using getInstance you could inject beans inside your unit test, i.e.:
public ServiceATest
{
@Inject
ServiceA serviceA;
@Before
public void before()
{
Injector injector = Guice.createInjector(new ServiceAModule());
injector.injectMembers(this);
}
}
Upvotes: 2