Reputation: 177
Is it true that in order to inject a class with Guice, the substituted class must be passed as an object argument to the constructor? I think this is "of course", but I thought I'd ask.
I wrote a class-under-test (CUT) with two constructors. One constructor takes one argument, an object of type depended-on-component (DOC). The other constructor calls the first, passing a new DOC(). The unit test uses an injector to direct the CUT to use MockDOC instead of DOC. When I remove the default CUT(), the unit test gets a run time error: com.google.inject.internal.ComputationException: java.lang.NoClassDefFoundError: org/objectweb/asm/ClassVisitor
The code:
//The class under test:
public class CUT {
DOC m_DOC;
@Inject
public CUT(DOC doc)
{
m_DOC = doc;
}
// When this ctor is added, there is a run time error:
// com.google.inject.internal.ComputationException: java.lang.NoClassDefFoundError: org/objectweb/asm/ClassVisitor
// @Inject
// public CUT()
// {
// this(new DOC());
// }
public boolean getVal()
{
return m_DOC.getVal();
}
}
// The depended-on-component:
public class DOC {
@Inject
public DOC()
{
}
// The REAL DOC returns 'true' MockDOC will return false
public Boolean getVal()
{
return true;
}
}
The mock DOC:
// This is the class we want CUT to call during unit test
class MockDOC extends DOC
{
@Override
public Boolean getVal()
{
// Real DOC returns 'true'. We return false so unit tester knows we got injected
return false;
}
}
The unit test that uses MockDOC to test CUT:
// Test the CUT class by substituting a mock for CUT's DOC
public class CUTTest {
@Test
public void testGetVal() throws Exception {
// Direct Guice to inject our MockDOC for CUT's use of DOC
Injector m_injector = Guice.createInjector(new CUTTestModule());
// Ask Guice to create a CUT object
CUT cut = m_injector.getInstance(CUT.class);
// The DOC returns 'true', while the mock DOC returns 'false. So we'll get 'false' if the injection
// succeeded
assertEquals(cut.getVal(), false);
}
// The class that we will pass to Guice to direct its injection
class CUTTestModule implements Module {
public CUTTestModule()
{
super();
}
@Override
public void configure(Binder binder) {
binder.bind(DOC.class).to(MockDOC.class);
}
}
}
Upvotes: 0
Views: 144
Reputation: 978
First, you can use Guice injection also on fields.
But regarding your main problem... why do add the @Inject annotation to the default constructor (the one without parameters)? There is no parameter to inject.
// When this ctor is added, there is a run time error:
// com.google.inject.internal.ComputationException: java.lang.NoClassDefFoundError: org/objectweb/asm/ClassVisitor
// @Inject
// public CUT()
// {
// this(new DOC());
// }
I would remove the @Inject
Upvotes: 1