Java 如何模拟@InjectMocks 类的方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30774358/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I mock methods of @InjectMocks class?
提问by Vova Yatsyk
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
来模拟它的方法?
采纳答案by Vova Yatsyk
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()
如果我们可以只是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();
}
}
Note: in case of 'spying' object we need to use doReturn
instead of thenReturn
(little explanation is here)
注意:在“间谍”对象的情况下,我们需要使用doReturn
而不是thenReturn
(这里有一些解释)
回答by NickJ
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.
如果那些其他类是您的应用程序的一部分,那么它们将有自己的单元测试。
NOTEthe 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 :) )
注意上面的代码可以用更多的注释来缩短,但为了解释起见,我想让它更明确(而且我不记得注释是什么:))