Reputation: 4637
I have this Service Interface
public interface ABC {
public String getAbc();
}
And I have this controller that uses this Service
public class Do {
@Inject ABC abc;
public String doAbc() {
String a = abc.getAbc();
}
}
In my Unit test, I want to be able to mock out this ABC and Not have to provide an actual implementation. Here is what works:
public class TestDo {
@Mock
private Do do;
@Mock
private ABC abc;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
do.abc = abc;
}
@Test
public void testDo() {
when(do.doAbc()).thenCallRealMethod();
do.doAbc();
assertSomething...
}
}
But what I do not want to do is do.abc = abc;
, from all my searches, in order to do @InjectMock, I need to provide a concrete class. Is there a way for me to use the interface but yet able to Inject the mocked interface into do without the need to exposed my ABC inject in Do Class? I want to make ABC a private variable, and still able to inject an interface through Mockito.
Upvotes: 6
Views: 20454
Reputation: 1407
public interface ABC {
public String getAbc();
}
public class Do {
@Inject
ABC abc;
public String doAbc() {
System.out.println("Injected abc is " + (abc == null ? "null" : "not null"));
return abc.getAbc();
}
}
public class TestDo {
@Mock
private ABC abc;
@InjectMocks
private Do ddo;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
@Test
public void simpleTest() {
System.out.println(ddo.doAbc());
}
}
output is:
Injected abc is not null
null
Upvotes: 6
Reputation: 77177
The example you gave is a perfect case for constructor injection: You can make your dependency private (and even final, which is always preferable when practical) and still build an instance without needing an injection framework:
public class Do {
private final ABC abc;
@Inject
public Do(final ABC abc) {
this.abc = abc;
}
public String doAbc() {
String a = abc.getAbc();
}
}
Upvotes: 4