Unit testing 莫基托堆内构件
我试图理解Mockito的内部功能。到目前为止,代码对我来说很难理解,我正在寻找对Mockito基本工作原理的高级调查 我已经编写了一些示例代码来演示我目前的理解:Unit testing 莫基托堆内构件,unit-testing,testing,mocking,mockito,internals,Unit Testing,Testing,Mocking,Mockito,Internals,我试图理解Mockito的内部功能。到目前为止,代码对我来说很难理解,我正在寻找对Mockito基本工作原理的高级调查 我已经编写了一些示例代码来演示我目前的理解: C类{ 字符串s; public void get(){return s;} // ... } C cm=模拟(C类); 当(cm.method())。然后返回(“字符串值”); 据我所知,“mock”方法只看到cm.get()的返回值。它如何知道方法的名称(以便存根)?另外,它如何知道传递给方法的参数 mockito API方
C类{
字符串s;
public void get(){return s;}
// ...
}
C cm=模拟(C类);
当(cm.method())。然后返回(“字符串值”);
据我所知,“mock”方法只看到cm.get()的返回值。它如何知道方法的名称(以便存根)?另外,它如何知道传递给方法的参数
mockito API方法调用内部对象的方法:
//org.mockito.mockito
公共静态ONGOINGSTUBING时(T方法调用){
返回MOCKITO_CORE.when(methodCall);
}
我已经跟随方法调用进入了几个不同的抽象、类和对象中,但是代码是如此的解耦以至于很难用这种方式理解
//org.mockito.internal.MockitoCore
公共ONGOINGSTUBING时(T方法调用){
mockingProgress.stubbingStarted();
返回(ongoingstubing)存根();
}
因此,如果有人了解内部结构或有讨论/博客帖子的链接,请共享:)(很抱歉,这太长了。TL;DR:Mockito在幕后记录方法调用。)
此时,您可能会认为cm
是C
的一个实例,您可能会错。相反,cm
是Mockito
写入的一个实例,它实现了C
(因此可以分配给C类型的字段/变量),但记录您请求的所有内容,并以存根的方式进行操作
让我们手动编写一个模拟类…并给它多一个方法,比如说intadd(inta,intb)
,它在实际类中添加a
和b
class MockC extends C {
int returnValue;
@Override int add(int a, int b) {
return returnValue;
}
}
那里!现在,无论何时调用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;
}
}
类MockC扩展了C{
List parameterValues=new ArrayList();
返回值;
@覆盖整数添加(整数a、整数b){
add(新对象[]{a,b});
返回值;
}
}
因此,现在您可以检查参数值
列表,并确保按预期调用它
事情是这样的:Mockito生成一个类似MockC的using,将所有交互和返回值保存在一个大的静态列表中。调用列表,而不是对象[]
每个mock的每个方法调用都是一个,但思想是一样的
要进一步了解RegisteredInvestations
以及它公开的removeLast
方法为何如此重要,请阅读中的代码。因为Mockito记录每个调用,所以当时,它自然会记录中包含的交互。Mockito在
时一看到,就会删除最后记录的交互(第45行),并将其用作存根的模板——从调用对象本身读取参数值
除了像eq
和any
这样的参数匹配器之外,这就解决了大部分问题:事实证明,它们只是被调用了。when
调用:对于add
示例,零匹配器告诉Mockito推断每个记录参数的相等性,两个匹配器告诉Mockito将这些参数从堆栈中弹出并使用它们。只有一个匹配器意味着Mockito无法判断要匹配的整数,并抛出经常令人困惑的结果,这就是为什么在使用匹配器时,如果匹配任何参数,就需要匹配每个参数
希望有帮助
EDIT:详细介绍了方法在时的工作原理
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;
}
}