Churk
Churk

Reputation: 4637

How to Mock an @Inject Interface

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

Answers (2)

Rustam
Rustam

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

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

Related Questions