带有 @Mock 和 @InjectMock 的 Mockito 需要但未调用:实际上,与此模拟的交互为零
Mockito with @Mock and @InjectMock Wanted but not invoked: Actually, there were zero interactions with this mock
我有一个 class 想要测试:
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);
}
}
我有下一个测试 class 工作正常并使用 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)));
}
}
但是为了遵循使用模拟的最佳实践,我想用 替换我的 Mockito.mock(dependency.class) @Mock 和@InjectMock 注释
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)));
}
}
执行以下步骤后我得到错误:需要但未调用:实际上,与此模拟的交互为零。我不明白我在这里遗漏了什么。
如果您有像 @Mock
和 @InjectMocks
这样的注释,您需要 运行 Junit 5 中带有特殊扩展的 Junit 测试:
@ExtendWith(MockitoExtension.class)
class MyTest {
@Mock
private Validator validator;
...
}
另请注意,此扩展程序会为您创建模拟并将值注入带注释的数据字段。
所以从技术上讲,像你在问题中展示的那样创建真实的对象是错误的:
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"
您可以关注 this tutorial 以获得更深入的示例和解释。
为了完整起见,如果您使用的是 Junit 4,则可以使用:
@RunWith(MockitoJUnitRunner.class)
public class DivisionTest {...}
我有一个 class 想要测试:
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);
}
}
我有下一个测试 class 工作正常并使用 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)));
}
}
但是为了遵循使用模拟的最佳实践,我想用 替换我的 Mockito.mock(dependency.class) @Mock 和@InjectMock 注释
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)));
}
}
执行以下步骤后我得到错误:需要但未调用:实际上,与此模拟的交互为零。我不明白我在这里遗漏了什么。
如果您有像 @Mock
和 @InjectMocks
这样的注释,您需要 运行 Junit 5 中带有特殊扩展的 Junit 测试:
@ExtendWith(MockitoExtension.class)
class MyTest {
@Mock
private Validator validator;
...
}
另请注意,此扩展程序会为您创建模拟并将值注入带注释的数据字段。 所以从技术上讲,像你在问题中展示的那样创建真实的对象是错误的:
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"
您可以关注 this tutorial 以获得更深入的示例和解释。
为了完整起见,如果您使用的是 Junit 4,则可以使用:
@RunWith(MockitoJUnitRunner.class)
public class DivisionTest {...}