問題描述
我很驚訝地發現以下簡單的代碼示例不適用于所有 Mockito 版本 > 1.8.5
I was very surprised to find out that following simple code example doesn't work for all Mockito versions > 1.8.5
@RunWith(MockitoJUnitRunner.class)
public class MockitoTest {
@Mock(name = "b2")
private B b2;
@InjectMocks
private A a;
@Test
public void testInjection() throws Exception {
assertNotNull(a.b2); //fails
assertNull(a.b1); //also fails, because unexpectedly b2 mock gets injected here
}
static class A{
private B b1;
private B b2;
}
interface B{}
}
在 javadocs (http://docs.mockito.googlecode.com/hg/latest/org/mockito/InjectMocks.html)有一句話:
In javadocs (http://docs.mockito.googlecode.com/hg/latest/org/mockito/InjectMocks.html) there is a quote:
注意 1:如果您有相同類型(或相同擦除)的字段,則為最好用匹配字段命名所有 @Mock 注釋字段,否則 Mockito 可能會感到困惑并且不會發生注入.
Note 1: If you have fields with the same type (or same erasure), it's better to name all @Mock annotated fields with the matching fields, otherwise Mockito might get confused and injection won't happen.
這是否意味著如果我有多個具有相同類型的字段,我不能只模擬其中一個,而是應該為具有相同類型的 ALL 字段定義 @Mock
?它是已知的限制嗎?是否有任何原因尚未修復?通過字段名稱匹配 @Mock
應該很簡單,不是嗎?
Does it mean that if I have several fields with same type I can't mock ONLY ONE of them but rather should define @Mock
for ALL fields with same type?
Is it known limitation and is there any reason why it wasn't fixed yet?
It should be straightforward to match @Mock
by fields names, isn't it?
推薦答案
看來 Mockito 使用了 他們的JavaDoc
It appears Mockito uses an algorithm described in their JavaDoc
如果我理解正確,它將首先按類型排序(在這種情況下只有 1 B),然后按名稱排序(這里沒有更改).它最終將使用 OngoingInjector 接口實現注入,這似乎是搜索第一個字段并注入它.
If I understand correctly, it will first sort on type (in this case only 1 B) and then sort on name (no changes here). It will finally inject using the OngoingInjector interface implementation, which appears to search for the first field and inject it.
由于您只定義了 1 個 B 并且 Mock 中有 B 的 2 個字段,因此它將看到第一個實例與該字段的匹配并停止.這是因為 mocks.size() == 1注入/過濾器/NameBasedCandidateFilter.java">NameBasedCandidateFilter.因此它將停止過濾并直接注入.如果您創建多個相同類型的模擬,它們將按名稱排序并相應地注入.
Since you only have 1 B defined and there are 2 fields of B in the Mock, it will see the match of the first instance to the field and stop. This is because mocks.size() == 1
in NameBasedCandidateFilter
. Therefore it will stop filtering and inject it directly. If you create multiple mocks of the same type, they will get sorted on Name and injected accordingly.
當我創建多個特定類型的模擬(但少于字段數量)時,我能夠讓它工作.
I was able to get it work when I created multiple mocks (but less than the number of fields) of a specific type.
@RunWith(MockitoJUnitRunner.class)
public class MockitoTest {
@Mock(name = "b2")
private B b2;
@Mock(name = "b3")
private B b3;
@InjectMocks
private A a;
@Test
public void testInjection() {
System.out.println(this.a);
}
static class A {
private B b1;
private B b2;
private B b3;
}
interface B {
}
}
這將正確地將 b2 注入 a.b2 并將 b3 注入 a.b3 而不是 a.b1 和 a.b2(在 A 中定義的前 2 個字段).
This will correctly inject b2 into a.b2 and b3 into a.b3 instead of a.b1 and a.b2 (the first 2 fields that are defined in A).
您始終可以在他們的存儲庫中留下一個 GitHub 問題,并對注入過濾算法進行增強或更改,以便查看.
You can always leave a GitHub issue on their repository with an enhancement or change on the injection filtering algorithm in order to be looked at.
這篇關于Mockito @InjectMocks 不適用于相同類型的字段的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!