例如我有处理程序:
@Component
public class MyHandler {
@AutoWired
private MyDependency myDependency;
public int someMethod() {
...
return anotherMethod();
}
public int anotherMethod() {...}
}
测试它我想写这样的东西:
@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);
}
}
但每当我试图嘲笑它时,它实际上会调用anotherMethod()
。我应该如何处理myHandler
来模拟其方法?
答案 0 :(得分:77)
首先,模拟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();
}
}
注意:如果是'间谍'对象我们需要使用doReturn
代替thenReturn
(很少解释here)
答案 1 :(得分:0)
在您的代码中,您根本不会测试MyHandler。你不想模拟你正在测试的东西,你想要调用它的实际方法。如果MyHandler有依赖关系,你可以模拟它们。
这样的事情:
public interface MyDependency {
public int otherMethod();
}
public class MyHandler {
@AutoWired
private MyDependency myDependency;
public void someMethod() {
myDependency.otherMethod();
}
}
在测试中:
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();
}
重点是要真正调用测试中的方法,但是模拟它们可能具有的任何依赖关系(例如调用其他类的方法)
如果那些其他类是你的应用程序的一部分,那么他们就有自己的单元测试。
注意上面的代码可以通过更多注释缩短,但为了解释起见,我想让它更明确(而且我也记不起注释是什么:)) / p>