Mockito @InjectMocks不适用于具有相同类型的字段 [英] Mockito @InjectMocks doesn't work for fields with same type

查看:271
本文介绍了Mockito @InjectMocks不适用于具有相同类型的字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很惊讶地发现以下简单的代码示例并不适用于所有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.

这是否意味着如果我有几个相同类型的字段我不能只模拟其中一个而是应该定义 @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并且模拟中有2个B字段,将看到第一个实例与该字段的匹配并停止。这是因为 mocks.size()== 1 mockito / internal / configuration / injection / filter / 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不适用于具有相同类型的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆