mockito接口没法赋值
使用Mockito进行Java类的模拟和存根的任何人,可能都熟悉InjectMocks -annotation。 在要测试的类上使用此批注,Mockito将尝试通过构造函数注入,setter注入或属性注入来注入模拟。 魔术成功了,它无声地失败了,或者抛出了MockitoException
。
我想解释什么原因导致“ MockitoException:无法实例化名为xxx的@InjectMocks字段! 原因:类型是接口”以及解决方法。
问题
考虑以下JUnit 5测试,该测试可以验证女服务员是否可以正确提供早餐。 厨房工作人员中的任何人都可以提供早餐,并且该测试会验证当提供早餐时,咖啡机开始冲泡咖啡,而烤面包机开始烘烤。
@ExtendWith (MockitoExtension. class ) public class WaitressTest { @Mock CoffeeMachine coffeeMachine; @Mock Toaster toaster; @InjectMocks KitchenStaff waitress; @Test void should_serve_breakfast() { waitress.serve(BREAKFAST); verify(coffeeMachine).brew(); verify(toaster).toast(); } } interface KitchenStaff { void serve(MealType mealType); } Waitress class implements KitchenStaff { CoffeeMachine coffeeMachine; Toaster toaster; //... @Override public void serve(MealType mealType) { coffeeMachine.brew(); toaster.toast(); } }
出于此测试的目的,Mockito模拟了协作的coffeeMachine
和toaster
-因此它们需要Mock
注释-这样我们可以验证是否调用了预期的方法。 女服务员是真的 ,她正在接受测试。 通过在她身上放置@InjectMocks
,Mockito创建一个实例并传入两个协作者-然后调用我们实际的@Test
-annotated方法。
不幸的是,它失败了:一旦运行测试,Mockito就会引发运行时异常: “无法实例化名为'waitress'的@InjectMocks字段! 原因:“ KitchenStaff”类型是接口。”

原因
幸运的是,最近Mockito的错误消息已得到改进,并且清楚地指出了问题所在: KitchenStaff
类型是一种接口。
- 我们有一个界面。
interface KitchenStaff { void serve(MealType mealType); }
- 我们对Mockito说:“实例化此接口”(什么?)
@InjectMocks KitchenStaff waitress
- 嘿,那不对!
您不能仅在接口上使用@InjectMocks
,因为Mockito需要知道要实例化的具体类 。
请记住,您正在测试的单元是通常是真实的少数幸运之一。 KitchenStaff
只是一个行为合同, Waitress
实际上是获得酬劳以供应早餐。
解
与使用抽象类一样 ,也有一些,但是归结为: 在实例声明时提供具体的类型。
给Mockito提供实现接口的类。
A)声明具体类型
对@InjectMocks
字段的类型使用具体的实现。
@InjectMocks Waitress waitress;
B)分配具体类型
继续对@InjectMocks
字段使用接口的类型,但是使用具体的实现对其进行初始化。
@InjectMocks KitchenStaff waitress = new Waitress()
或者当然在声明和初始化中使用具体类型,当然也可以
然而…
但是,您的受测类是否期望(必需)协作者作为构造函数的参数?
(我当然希望如此!)
例如,考虑以下单个构造函数:
Waitress class implements KitchenStaff { final CoffeeMachine coffeeMachine; final Toaster toaster; Waitress(CoffeeMachine coffeeMachine, Toaster toaster) { this .coffeeMachine = coffeeMachine; this .toaster = toaster; }
然后,在没有一个无参数的构造函数, 编译器会告诉你调用适当的构造函数,并提供论据就在那里,现在 。
@InjectMocks KitchenStaff waitress = new Waitress() ^^ compiler error
A.自己提供参数来解决。
// compiles again @InjectMocks KitchenStaff waitress = new Waitress(coffeeMachine, toaster);
B.删除@InjectMocks
。 您不再需要它 。
KitchenStaff waitress; @BeforeEach void setup() { waitress = new Waitress(coffeeMachine, toaster); }
结论
相信女服务员为您做些敬酒。
翻译自: https://www.javacodegeeks.com/2020/07/mockito-cannot-instantiate-injectmocks-field-the-type-is-an-interface.html
mockito接口没法赋值