【问题标题】:Why Cannot I use Mock and InjectMocks together?为什么我不能同时使用 Mock 和 InjectMocks?
【发布时间】:2014-05-13 13:15:00
【问题描述】:

有效构造:

@InjectMocks
SomeClass sc = mock(SomeClass.class);

无效的构造:

@InjectMocks
@Mock
SomeClass sc;

我想将模拟注入另一个模拟。我只想使用注释样式。

为什么在 Mockito 中禁止二次构造?

更新

示例:

    public class ArrTest {
    private SomeClass someClass;

    public List<String> foo(){
        anotherMethod(); // I suppose that this method works. I want to test it separately.
        //logic which I need to test
        return someClass.doSmth();// I suppose that this method works. I want to test it separately.
    }
    public void anotherMethod(){
        ///...
    }
}

public class SomeClass {
    public List<String> doSmth(){
        return null;
    }
}

测试

public class ArrTestTest {
    @InjectMocks
    ArrTest arrTest = Mockito.mock(ArrTest.class);
    @Mock
    SomeClass someClass;
    @Test
    public void fooTest(){        
         Mockito.when(someClass.doSmth()).thenReturn(new ArrayList<String>());
         Mockito.doNothing().when(arrTest).anotherMethod();
         System.out.println(arrTest.foo());
    }

}

【问题讨论】:

  • 通过模拟arrTest,其所有方法和字段的实现变得无关紧要。 Mockito.when().thenReturn() 调用定义了“实现”(我松散地使用了这个术语)。 Mockito 无法将模拟注入 arTest 模拟,因为没有要注入的字段,请参阅下面 @jeff-bowman 的答案。看起来您正在尝试做的是部分模拟,在这种情况下,您需要创建一个 @Spy 和/或将行为定义为 when(mock.someCall().thenCallRealMethod()

标签: java unit-testing testing mockito


【解决方案1】:

听起来您正在尝试做一些没有意义的事情。您不应该需要将任何依赖项注入到您的模拟中,因为根据定义,模拟没有任何行为,直到您使用 when(mock.someMethod()).thenAnswer() 或一些变体定义它。

(除非您使用的是spy(),但您明确表示您使用的是@Mock)。

也许您可以解释一下您的用例以及为什么要尝试将依赖项注入到模拟中?

【讨论】:

    【解决方案2】:

    @InjectMocks 明确表示带注释的字段将不包含模拟。注释 @InjectMocks @Mock 不仅不受支持,而且自相矛盾。

    return stubs wherever possible,使用这个:

    @Mock(answer=Answers.RETURNS_DEEP_STUBS)
    YourClass mockYourClassWithDeepStubs;
    

    但请注意the official documentation for this Answer:

    警告: 常规干净代码很少需要此功能!把它留给遗留代码。模拟一个模拟返回一个模拟,返回一个模拟,(...),返回一些有意义的暗示违反德墨忒耳法则或模拟一个值对象(一个众所周知的反模式)。

    我有一天在网上看到的好名言:每次模拟返回模拟时,仙女就会死去

    【讨论】:

      【解决方案3】:

      模拟没有任何真正的实现。 @InjectMocks 将尝试为已经创建的任何模拟对象查找并调用设置器并将它们传递进来。Mockito“知道”这在模拟中有点毫无意义,因为没有任何方法可以取回模拟对象出去,更不用说对他们做任何有意义的事情了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-01-18
        • 1970-01-01
        • 2015-11-22
        • 2020-09-13
        • 1970-01-01
        • 2017-09-13
        • 2013-12-29
        • 1970-01-01
        相关资源
        最近更新 更多