Search code examples
javajakarta-eemockito

Injecting multiple implementations of same interface through Instance<T> in test class


I'm struggling with writing unit tests for one of my classes. The main class:

public class MainClass {
    ...

    private Instance<BaseInterface> steps;

    @Inject
    public void setSteps(Instance<BaseInterface> steps) { this.steps = steps; }

    @Asynchronous
    public void callingMethod() {
        ...
        ImmutableList<BaseInterface> stepList = STEP_ORDERING.immutableSortedCopy(steps); // Here the NPE is being thrown when calling method from test class
        ...
    }
}

There are 5 specific implementations of BaseInterface, all 5 are correctly injected through setter by CDI at runtime (one of the implementation is annotated with @Named, the rest do not have this annotation).

However, calling the wrapper method callingMethod from the test class throws NPE. The test class:

@RunWith(MockitoJUnitRunner.class)
public class MainClassTest {

    @InjectMocks
    private MainClass mainClass = new MainClass();
    @Mock
    private Instance<BaseInterface> steps;

    @Test
    public void test() {
        ...

        mainClass.callingMethod(); // Throws NPE

        ...
    }
}

As far as I'm concerned, Mockito does not take care of bean dependency injection like CDI. Therefore, is there a way in which to tell Mockito to mock all implementations of BaseInterface and inject them into the MainClass?

Version details: Java 8, Mockito 2.8.9, JUnit 4

Thank you!


Solution

  • Solved. The problem was not caused by Mockito, but by the method STEP_ORDERING.immutableSortedCopy which behind the scenes calls iterator() method from Instance<T> which returned null (since it extends Iterable<T>).

    Mocking the iterator does the trick:

    Iterator<BaseInterface> iteratorMock = (Iterator<BaseInterface>) mock(Iterator.class);
    when(steps.iterator()).thenReturn(iteratorMock);
    

    or by creating an actual instance of iterator:

    Iterator<BaseInterface> iteratorActual = new Iterator<BaseInterface>(){
    // implementation here
    };
    when(steps.iterator()).thenReturn(iteratorActual );