Mockito with @Mock and @InjectMock Wanted but not invoked: Actually, there were zero interactions with this mock

Alex :

I have a class that I want to test:

   public class DivisionCalculator {
    private final Validator validator;
    private final MathProvider mathProvider;
    private final ViewProvider viewProvider;

    public DivisionCalculator(Validator validator, MathProvider mathProvider, ViewProvider viewProvider) {
        this.validator = validator;
        this.mathProvider = mathProvider;
        this.viewProvider = viewProvider;
    }

    public String calculate(int dividend, int divisor) {
        validator.validate(dividend, divisor);

        List<DivisionStep> items = mathProvider.calculate(dividend, divisor);

        DivisionResult result = DivisionResult.builder()
                .dividend(dividend)
                .divisor(divisor)
                .finalResult(mathProvider.finalResult(items))
                .items(items)
                .build();

        return viewProvider.provideView(result);
    }
}

I have next following test class that works fine and pass the test using Mockito.mock(dependency.class)

    public class DivisionCalculatorTest {

    private ViewProvider viewProvider = Mockito.mock(ViewProvider.class);
    private MathProvider mathProvider = Mockito.mock(MathProvider.class);
    private Validator validator = Mockito.mock(Validator.class);

    private DivisionCalculator divisionCalculator = new DivisionCalculator(validator, mathProvider, viewProvider);

    DivisionResult makeDivision(int dividend, int divisor) {
        List<DivisionStep> items = mathProvider.calculate(dividend, divisor);
        return DivisionResult.builder()
                .dividend(dividend)
                .divisor(divisor)
                .finalResult(mathProvider.finalResult(items))
                .items(items)
                .build();
    }

    @Test
    void divisionCalculatorShouldSuccessfullyCallHisComponents() {

        divisionCalculator.calculate(4, 2);

        Mockito.verify(validator).validate(Mockito.anyInt(), Mockito.anyInt());
        Mockito.verify(mathProvider).calculate(Mockito.anyInt(),Mockito.anyInt());
        Mockito.verify(viewProvider).provideView(refEq(makeDivision(4, 2)));

    }
}

But in order to follow the best practices working with mocks, I want to replace my Mockito.mock(dependency.class) with @Mock and @InjectMock annotations

public class DivisionTest {
    @Mock
    private Validator validator = new Validator();
    @Mock
    private ViewProvider viewProvider = new ViewProvider();
    @Mock
    private MathProvider mathProvider = new MathProvider();

    @BeforeEach
    void setup() {
        MockitoAnnotations.initMocks(this);
    }
    @InjectMocks
    private DivisionCalculator divisionCalculator = new DivisionCalculator(validator, mathProvider, viewProvider);

    DivisionResult makeDivision(int dividend, int divisor) {
        List<DivisionStep> items = mathProvider.calculate(dividend, divisor);
        return DivisionResult.builder()
                .dividend(dividend)
                .divisor(divisor)
                .finalResult(mathProvider.finalResult(items))
                .items(items)
                .build();
    }

    @Test
    void divisionCalculatorShouldSuccessfullyCallHisComponents() {

        divisionCalculator.calculate(4, 2);

        Mockito.verify(validator).validate(4, 2);
        Mockito.verify(mathProvider).calculate(4, 2);
        Mockito.verify(viewProvider).provideView(refEq(makeDivision(4, 2)));
    }
}

After following steps I got Error: Wanted but not invoked: Actually, there were zero interactions with this mock. I can't understand what am I missing here.

Mark Bramnik :

If you have annotations like @Mock and @InjectMocks you need to run the Junit test with a special extension in Junit 5:

@ExtendWith(MockitoExtension.class)
class MyTest {
    @Mock
    private Validator validator;
     ...
}

Also note that this extension creates mocks for you and injects the values into the annotated data fields. So technically its wrong to create the real objects like you've shown in the question:

public class DivisionTest {
    @Mock
    private Validator validator = new Validator();  // this is wrong, don't use "new"
    @Mock
    private ViewProvider viewProvider = new ViewProvider(); // this is wrong, don't use "new"
    @Mock
    private MathProvider mathProvider = new MathProvider(); // this is wrong, don't use "new"

You can follow this tutorial for more in-depth example and explanations.

Just for the sake of completeness, if you were using Junit 4, you could use:

@RunWith(MockitoJUnitRunner.class)
public class DivisionTest {...}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=319308&siteId=1