我如何模拟@InjectMocks类的方法?

Vov*_*syk 48 java unit-testing mocking mockito

例如我有处理程序:

@Component
public class MyHandler {

  @AutoWired
  private MyDependency myDependency;

  public int someMethod() {
    ...
    return anotherMethod();
  }

  public int anotherMethod() {...}
}
Run Code Online (Sandbox Code Playgroud)

测试它我想写这样的东西:

@RunWith(MockitoJUnitRunner.class}
class MyHandlerTest {

  @InjectMocks
  private MyHandler myHandler;

  @Mock
  private MyDependency myDependency;

  @Test
  public void testSomeMethod() {
    when(myHandler.anotherMethod()).thenReturn(1);
    assertEquals(myHandler.someMethod() == 1);
  }
}
Run Code Online (Sandbox Code Playgroud)

但它实际上anotherMethod()只要我试图模仿它就会调用它.我该怎么做myHandler来嘲笑它的方法?

Vov*_*syk 87

首先,模拟MyHandler方法的原因可能如下:我们已经测试了anotherMethod()它并且它具有复杂的逻辑,那么为什么我们需要再次测试它(比如它的一部分someMethod())如果我们可以verify调用它?
我们可以做到:

@RunWith(MockitoJUnitRunner.class}
class MyHandlerTest {

  @Spy  
  @InjectMocks  
  private MyHandler myHandler;  

  @Mock  
  private MyDependency myDependency;  

  @Test  
  public void testSomeMethod() {  
    doReturn(1).when(myHandler).anotherMethod();  
    assertEquals(myHandler.someMethod() == 1);  
    verify(myHandler, times(1)).anotherMethod();  
  }  
}  
Run Code Online (Sandbox Code Playgroud)

注意:如果是'间谍'对象,我们需要使用doReturn而不是thenReturn(这里的解释很少)

  • 如果您同时使用 Spy 和 InjectMocks 注释,它不会注入任何内容 (2认同)

Joh*_*zek 10

上面的所有答案都非常好并且可能有用,因此在继续阅读我的文章之前,请确保您首先学习并理解这些原则。

在我的情况下,上述建议都不起作用。经过相当长的调试后,我将发布对我有帮助的内容。

如果您想从测试类中调用方法,@Spy则需要旁边的注释@InjectMocks(或Mockito.spy(XXX)调用或课程)

有趣的是,这些注释的顺序确实很重要!注释必须先于注释@Spy @InjectMocks

不管用

...

@InjectMocks
@Spy
private TestedObject instance

...
Run Code Online (Sandbox Code Playgroud)

将工作

...

@Spy
@InjectMocks
private TestedObject instance

...
Run Code Online (Sandbox Code Playgroud)