Java mockito @Mock 没有按预期注入命名的 @Resource

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22517127/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 16:12:54  来源:igfitidea点击:

mockito @Mock does not inject into named @Resource as expected

javadependency-injectionmockito

提问by Bill Turner

I have a class with three named @Resource members as follows:

我有一个包含三个名为 @Resource 成员的类,如下所示:

@Resource(name = "contactsPaginationRequestValidator")
private PaginationRequestValidator paginationRequestValidator;

@Resource(name = "integerMaxPaginationRequestValidator")
private PaginationRequestValidator integerMaxPaginationRequestValidator;

@Resource(name = "contactsSearchResultPaginationRequestValidator")
private PaginationRequestValidator contactsSearchResultPaginationRequestValidator;

After upgrading to Mockito 1.9.5 from 1.8.5, the test began failing. The test suite mocked PaginationRequestValidator only once as follows:

从 1.8.5 升级到 Mockito 1.9.5 后,测试开始失败。测试套件仅模拟 PaginationRequestValidator 一次,如下所示:

@Mock
private PaginationRequestValidator mockPaginationRequestValidator;

This resulted in only the third of the three instances being injected as the following sysout makes clear:

这导致仅注入了三个实例中的第三个,如下面的系统输出所示:

paginationRequestValidator (contactsPaginationRequestValidator) is null
integerMaxPaginationRequestValidator (integerMaxPaginationRequestValidator) is null
contactsSearchResultPaginationRequestValidator (contactsSearchResultPaginationRequestValidator) is mockPaginationRequestValidator

Obviously, there was a change in behavior between the two versions. I am assuming the older version injected the mock into all three of fields - which would still be an acceptable solution to me.

显然,两个版本之间的行为发生了变化。我假设旧版本将模拟注入所有三个字段 - 这对我来说仍然是一个可以接受的解决方案。

Being the smart guy that I am, I figured I could get the test to pass by providing the name associated with the resource, as follows:

作为一个聪明人,我想我可以通过提供与资源关联的名称来通过测试,如下所示:

@Mock(name = "contactsPaginationRequestValidator")
private PaginationRequestValidator mockPaginationRequestValidator;

This resulted in similar, but subtly different results. The third field, not the expected targeted field was mocked, as above, but the it was mocked with the name provided in the @Mock. See the sysout:

这导致了相似但略有不同的结果。第三个字段,不是预期的目标字段被模拟,如上所述,但它被@Mock 中提供的名称模拟。查看系统输出:

paginationRequestValidator (contactsPaginationRequestValidator) is null
integerMaxPaginationRequestValidator (integerMaxPaginationRequestValidator) is null
contactsSearchResultPaginationRequestValidator (contactsSearchResultPaginationRequestValidator) is contactsPaginationRequestValidator

This is totally unexpected behavior. Yet, there is more. When I then added a similar mock for the second field, all the fields ended being mocked as expected:

这是完全出乎意料的行为。然而,还有更多。当我为第二个字段添加一个类似的模拟时,所有字段都按预期结束被模拟:

@Mock(name = "contactsPaginationRequestValidator")
private PaginationRequestValidator mockPaginationRequestValidator;

@Mock(name = "integerMaxPaginationRequestValidator")
private PaginationRequestValidator mockIntegerMaxPaginationRequestValidator;

Sysout:

系统输出:

paginationRequestValidator (contactsPaginationRequestValidator) is contactsPaginationRequestValidator
integerMaxPaginationRequestValidator (integerMaxPaginationRequestValidator) is integerMaxPaginationRequestValidator
contactsSearchResultPaginationRequestValidator (contactsSearchResultPaginationRequestValidator) is null

While this is exactly as I would expect, it seems completely contradictory to the previous tries.

虽然这完全符合我的预期,但它似乎与之前的尝试完全矛盾。

I have the documentation that explains this behavior, but it does not suggest a way to inject the same mock into all three. Is this possible, or must I create multiple mocks and then change individual test cases to use the "correct" mock?

我有解释这种行为的文档,但它没有建议将相同的模拟注入所有三个的方法。这是可能的,还是我必须创建多个模拟,然后更改单个测试用例以使用“正确”的模拟?

The test suite uses the @InjectMocks annotation.

测试套件使用@InjectMocks 注释。

采纳答案by JB Nizet

The documentation of InjectMockssays:

文档InjectMocks说:

Field injection; mocks will first be resolved by type, then, if there is several property of the same type, by the match of the field name and the mock name.

现场注入;mocks 将首先按类型解析,然后,如果有多个相同类型的属性,则通过字段名称和模拟名称的匹配。

So you need 3 mocks, each having the name of the field to inject with the mock.

所以你需要 3 个模拟,每个模拟都有要注入模拟的字段的名称。