xst*_*xst 3 testing unit-testing mocking internals mockito
我试图了解Mockito的内部功能.到目前为止,我很难理解代码,而且我正在寻找关于Mockito基本工作的高级调查.
我写了一些示例代码来证明我目前的理解:
class C {
String s;
public void getS() { return s; }
// ...
}
C cm = mock( C.class);
when( cm.method() ).thenReturn( "string value");
Run Code Online (Sandbox Code Playgroud)
据我所知,'mock'方法只能看到cm.getS()的返回值.怎么知道方法的名称是什么(为了存根)?另外,它如何知道传递给方法的参数?
mockito API方法调用内部对象的方法:
// org.mockito.Mockito
public static <T> OngoingStubbing<T> when(T methodCall) {
return MOCKITO_CORE.when(methodCall);
}
Run Code Online (Sandbox Code Playgroud)
我已经将方法调用跟踪到几个不同的抽象,类和对象,但代码是如此分离,以至于很难理解这种方式.
// org.mockito.internal.MockitoCore
public <T> OngoingStubbing<T> when(T methodCall) {
mockingProgress.stubbingStarted();
return (OngoingStubbing) stub();
}
Run Code Online (Sandbox Code Playgroud)
因此,如果有人了解内部或有一个讨论/博客文章的链接,请分享:)
Jef*_*ica 15
(抱歉,这很长.TL; DR:Mockito在幕后记录方法调用.)
C cm = mock(C.class);
Run Code Online (Sandbox Code Playgroud)
在这一点上,你可能认为这cm是C......的一个例子,你就错了.相反,cm是实现的代理对象 Mockito写入的实例C(因此可以分配给类型C的字段/变量),但记录您要求的所有内容并按照您将其存根的方式运行.
让我们手动编写一个模拟类...并给它多方法,让我们说int add(int a, int b),这将增加a并b在实际的类.
class MockC extends C {
int returnValue;
@Override int add(int a, int b) {
return returnValue;
}
}
Run Code Online (Sandbox Code Playgroud)
那里!现在每当你打电话时add,它都不会添加这两个数字,而只是返回单个返回值.说得通.但是,如果您想稍后验证通话怎么办?
class MockC extends C {
List<Object[]> parameterValues = new ArrayList<>();
int returnValue;
@Override int add(int a, int b) {
parameterValues.add(new Object[] { a, b });
return returnValue;
}
}
Run Code Online (Sandbox Code Playgroud)
所以现在你可以查看parameterValues列表并确保按预期调用它.
事情就是这样:Mockito 使用CGLIB生成一个代理,它自动地像MockC一样,保持所有交互并将值返回到一个大的静态列表中.调用该列表RegisteredInvocations,而不是Object[]每个模拟的每个方法调用都是一个Invocation,但想法是相同的.
为了更多地了解它暴露RegisteredInvocations的removeLast方法以及为什么它如此重要,请阅读代码InvocationContainer.因为Mockito记录每个电话,它会自然地记录其中包含的交互when.一旦Mockito看到when,它将删除最后记录的交互(InvocationContainerImpl.java第45行)并将其用作存根的模板 - 从Invocation对象本身读取参数值.
除了参数匹配器之外,它会处理大部分内容,eq并且any:结果证明那些只是保持在一个名为的花哨堆栈上ArgumentMatcherStorage.该when调用检查堆栈中有多少匹配器:对于该add示例,零匹配器告诉Mockito推断与每个记录的参数的相等性,并且两个匹配器告诉Mockito从堆栈弹出那些并使用它们.只有一个匹配器意味着Mockito无法判断你正在尝试匹配哪个整数并抛出常常令人困惑的原因InvalidUseOfMatchersException,这就是为什么当使用匹配器时,如果你匹配任何参数,你需要匹配每个参数.
希望有所帮助!
编辑: 此答案描述了该when方法如何在更多技术细节中工作.
| 归档时间: |
|
| 查看次数: |
1843 次 |
| 最近记录: |