我知道有重复,但是没有给出关于实际问题的答案。
How to verify if method is called on System under test (not a mock)
我有一堂课
class A {
public long a() {
if(something) {
return quicklyCalculatedResult
} else {
return b() run on separate thread, with this one blocked
}
}
public long b() {} //doStuffOnCurrentThread;
}
我对b()有一套完整的测试,可以完成繁重的工作。不幸的是,我不得不像a()(旧版代码)那样丑陋地思考,并且我不想复制所有测试。方法b()的。另外,这两个都需要公开。
我想验证在某些情况下a()调用b(),但是我不能这样做,因为经过测试的类不是模拟的。我需要一种方法来验证是否在真实对象上调用了该方法,而不仅仅是一个模拟。
答案 0 :(得分:2)
您可以使用@Spy
或A
使Mockito.spy()
成为间谍。这将允许您调用和测试a()
方法逻辑,但也可以将b()
替换为不变式。可以用一个列表来说明:
List list = new LinkedList();
List spy = Mockito.spy(list);
// Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
// You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
答案 1 :(得分:2)
Mockito和其他kotlin模拟库提供部分模拟或类似功能。您可以指定要调用的实际方法,而其他方法仍然是存根:
Mockito Java示例:
A classUnderTest = mock(A.class);
when(classUnderTest.a()).thenCallRealMethod();
classUnderTest.a();
verify(classUnderTest).b()
有关部分模拟,请参见模拟Documentation。不鼓励使用部分模拟,因为它不适合良好的OOP设计,但是在您的情况下,它符合其预期的目的,即测试困难的旧代码。
香草Mockito的Kotlin示例:
val classUnderTest = mock(A::class.java)
`when`(classUnderTest.a()).thenCallRealMethod()
classUnderTest.a()
verify(classUnderTest).b()
mockito-kotlin提供了一些扩展,这些扩展使您可以以更加科特林惯用的方式使用模仿。不幸的是,似乎没有一种以kotlin惯用的方式进行部分模拟的方法,但是可以在模仿者kotlin中实现,就像这样:
val classUnderTest = mock<A>()
doCallRealMethod().whenever(classUnderTest).a()
classUnderTest.a()
verify(classUnderTest).b()
MockK是一个惯用的kotlin模拟库,允许间谍使用此功能。创建类的spy
之后,您可以选择对方法进行存根:
val classUnderTest = spyk<A>()
every { classUnderTest.b() } returns 1L
classUnderTest.a()
verify { classUnderTest.b() }