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

时间:2022-09-11 20:55:04

For example I have handler:

例如我有处理程序:

@Component
public class MyHandler {

  @AutoWired
  private MyDependency myDependency;

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

  public int anotherMethod() {...}
}

to testing it I want to write something like this:

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

@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);
  }
}

But it actually calls anotherMethod() whenever I try to mock it. What should I do with myHandler to mock its methods?

但是每当我试图模仿它时,它实际上会调用anotherMethod()。我应该怎么做myHandler来模拟它的方法?

2 个解决方案

#1


64  

First of all the reason for mocking MyHandler methods can be the following: we already test anotherMethod() and it has complex logic, so why do we need to test it again (like a part of someMethod()) if we can just verify that it's calling?
We can do it through:

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

@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();  
  }  
}  

Note: in case of 'spying' object we need to use doReturn instead of thenReturn(little explanation is here)

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

#2


0  

In your code, you are not testing MyHandler at all. You don't want to mock what you are testing, you want to call its actual methods. If MyHandler has dependencies, you mock them.

在您的代码中,您根本不会测试MyHandler。你不想模拟你正在测试的东西,你想要调用它的实际方法。如果MyHandler有依赖项,那么你可以模拟它们。

Something like this:

像这样的东西:

public interface MyDependency {
  public int otherMethod();
}

public class MyHandler {
  @AutoWired
  private MyDependency myDependency;

  public void someMethod() {
    myDependency.otherMethod();
  }
}

And in test:

在测试中:

private MyDependency mockDependency;
private MyHandler realHandler;

@Before
public void setup() {
   mockDependency = Mockito.mock(MyDependency.class);
   realHandler = new MyHandler();
   realhandler.setDependency(mockDependency); //but you might Springify this 
}

@Test
public void testSomeMethod() {

  //specify behaviour of mock
  when(mockDependency.otherMethod()).thenReturn(1);

  //really call the method under test
  realHandler.someMethod();
}

The point is to really call the method under test, but mock any dependencies they may have (e.g. calling method of other classes)

关键是要真正调用测试中的方法,但是模拟它们可能具有的任何依赖性(例如,调用其他类的方法)

If those other classes are part of your application, then they'd have their own unit tests.

如果那些其他类是您的应用程序的一部分,那么他们将有自己的单元测试。

NOTE the above code could be shortened with more annotations, but I wanted to make it more explicit for the sake of explanation (and also I can't remember what the annotations are :) )

注意上面的代码可以用更多的注释缩短,但我想为了解释而使它更明确(而且我也记不起注释是什么:))

#1


64  

First of all the reason for mocking MyHandler methods can be the following: we already test anotherMethod() and it has complex logic, so why do we need to test it again (like a part of someMethod()) if we can just verify that it's calling?
We can do it through:

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

@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();  
  }  
}  

Note: in case of 'spying' object we need to use doReturn instead of thenReturn(little explanation is here)

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

#2


0  

In your code, you are not testing MyHandler at all. You don't want to mock what you are testing, you want to call its actual methods. If MyHandler has dependencies, you mock them.

在您的代码中,您根本不会测试MyHandler。你不想模拟你正在测试的东西,你想要调用它的实际方法。如果MyHandler有依赖项,那么你可以模拟它们。

Something like this:

像这样的东西:

public interface MyDependency {
  public int otherMethod();
}

public class MyHandler {
  @AutoWired
  private MyDependency myDependency;

  public void someMethod() {
    myDependency.otherMethod();
  }
}

And in test:

在测试中:

private MyDependency mockDependency;
private MyHandler realHandler;

@Before
public void setup() {
   mockDependency = Mockito.mock(MyDependency.class);
   realHandler = new MyHandler();
   realhandler.setDependency(mockDependency); //but you might Springify this 
}

@Test
public void testSomeMethod() {

  //specify behaviour of mock
  when(mockDependency.otherMethod()).thenReturn(1);

  //really call the method under test
  realHandler.someMethod();
}

The point is to really call the method under test, but mock any dependencies they may have (e.g. calling method of other classes)

关键是要真正调用测试中的方法,但是模拟它们可能具有的任何依赖性(例如,调用其他类的方法)

If those other classes are part of your application, then they'd have their own unit tests.

如果那些其他类是您的应用程序的一部分,那么他们将有自己的单元测试。

NOTE the above code could be shortened with more annotations, but I wanted to make it more explicit for the sake of explanation (and also I can't remember what the annotations are :) )

注意上面的代码可以用更多的注释缩短,但我想为了解释而使它更明确(而且我也记不起注释是什么:))