5

我是 .NET 人 - 我主要使用 C# 编写代码。

从 C# 3.0 开始,我们可以利用 lambda 表达式和表达式树来使用静态反射。例如,可以GetMethodName在下面的代码片段中实现返回传入参数的方法名称:

string methodName = GetMethodName( o => o.DoSomething());
Console.WriteLine(methodName); // displays "DoSomething"

现在,当我查看 Java 世界中的 Mockito 示例(或 EasyMock 示例)时,我看到:

LinkedList mockedList = mock(LinkedList.class);
when(mockedList.get(0)).thenReturn("first");

它是如何工作的?

该方法如何when工作?它如何解释mockedList.get(0)为对 get 方法的调用,其中 0 作为参数而不是值传递?

4

4 回答 4

5

模拟库通常不适用于表达式树。他们构建了一个实现适当接口的类型,并通过记录或验证方法调用并返回预编程的响应来响应方法调用。这通常通过代理(例如.NET 中的RealProxy ,Java 中的代理)或动态代码生成来完成。

在 EasyMock 的情况下,它使用Proxy(无论如何用于接口),正如您在源代码中看到的那样:查看org.easymock.internal.JavaProxyFactory.

于 2009-03-09T14:06:38.820 回答
4

Java 模拟库通常是这样工作的:

当您创建模拟时,会创建一个实际的代理(无论是来自接口还是子类),该实例处于“录制模式”。这意味着记录任何后续调用(方法名称、参数、预期返回)。请注意,录音模式下的代理实际上只记录呼叫。本身不涉及反射。没有元数据发现等。当然,这些库做了一些技巧(例如将调用存储在线程局部变量中以处理返回 void 的方法),但想法保持不变。

然后,当“重播模式”启动时,模拟实例仅检查调用列表中的期望(方法+参数和返回值)。

于 2009-03-09T16:55:50.410 回答
2

我从未使用过 mockito 或 easymock,但我认为该调用不会像您认为的那样。它不以mockedList.get(0)任何特殊方式解释。该方法getmockedList对象上正常执行,其结果交给when.

于 2009-03-09T14:03:16.223 回答
1

mockedList.get(0)是方法调用的语法,并且正是这样做的。该方法的作用并不完全清楚。mockedList的运行时类型将是LinkedList该方法返回的子类mock,它可以在模拟框架认为合适的情况下实现。

于 2009-03-09T14:05:33.550 回答