c# - 使用给出异常的表达式验证方法调用
问题描述
我正在尝试通过使用Linq 表达式方法 ApiVerify
来使用 Moq 的方法(以验证是否调用了方法)。
下面是两个单元测试。TestMethod1 使用了一个运行良好的简单 lambda 表达式。
我想在TestMethod2中实现和TestMethod1一模一样;但是通过使用 Linq 表达式方法 Api。但是当我运行TestMethod2时,它给出了异常:
类型 Castle.Proxies.ISomeInterfaceProxy 和 Moq.Mock 之间没有定义强制表达式。
谁能告诉我我做错了什么?
using System;
using System.Linq.Expressions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace UnitTestProject1
{
[TestClass]
public class UnitTest2
{
public interface ISomeInterface
{
void DoSomething(string param1, string param2);
}
public class ImplementationClass
{
private ISomeInterface _someInterface;
public ImplementationClass(ISomeInterface someInterface)
{
_someInterface = someInterface;
}
public void Investigate(string param1, string param2)
{
_someInterface.DoSomething(param1, param2);
}
}
[TestMethod]
public void TestMethod1()
{
Mock<ISomeInterface> myMock = new Mock<ISomeInterface>();
ImplementationClass myImplementationClass = new ImplementationClass(myMock.Object);
string Arg1 = "Arg1";
string Arg2 = "Arg2";
myImplementationClass.Investigate(Arg1, Arg2);
Expression<Action<ISomeInterface>> lambdaExpression = m => m.DoSomething(Arg1, Arg2);
myMock.Verify(lambdaExpression);
}
[TestMethod]
public void TestMethod2()
{
Mock<ISomeInterface> myMock = new Mock<ISomeInterface>();
ImplementationClass myImplementationClass = new ImplementationClass(myMock.Object);
string Arg1 = "Arg1";
string Arg2 = "Arg2";
myImplementationClass.Investigate(Arg1, Arg2);
var methodInfo = myMock.Object.GetType().GetMethod("DoSomething");
var call = Expression.Call(Expression.Constant(myMock.Object), methodInfo, Expression.Constant(Arg1), Expression.Constant(Arg2));
Expression<Action<ISomeInterface>> expression = Expression.Lambda<Action<ISomeInterface>>(call, Expression.Parameter(typeof(ISomeInterface)));
myMock.Verify(expression); // Exception comes from here.
}
}
}
解决方案
第一个问题是你不能使用.Object
Mock 作为类型的来源,因为它不是“正确的”类型。最安全的方法是使用接口本身作为类型的来源。
第二个问题是您需要为 lambda 表达式指定一个参数,而这必须是您调用该方法的对象;就像您在测试 1 中所做的那样m => m.DoSomething
。
作为奖励提示,我建议使用nameof()
而不是硬编码的字符串名称 - 这意味着如果您输入错误,您将得到编译时错误,而不是运行时错误。
我加入了“Arrange Act Assert”模式以提高可读性;这一点特别重要,因为这种方法比简单的 lambda 表达式更难阅读,内联到 Verify 方法的参数中。
所以固定版本看起来像这样......
[TestMethod]
public void TestMethod2()
{
// Arrange.
Mock<ISomeInterface> myMock = new Mock<ISomeInterface>();
ImplementationClass myImplementationClass = new ImplementationClass(myMock.Object);
string Arg1 = "Arg1";
string Arg2 = "Arg2";
// Act.
myImplementationClass.Investigate(Arg1, Arg2);
// Assert.
var methodInfo = typeof(ISomeInterface).GetMethod(nameof(ISomeInterface.DoSomething));
var parameter = Expression.Parameter(typeof(ISomeInterface), "m");
var call = Expression.Call(parameter, methodInfo, Expression.Constant(Arg1), Expression.Constant(Arg2));
Expression<Action<ISomeInterface>> expression = Expression.Lambda<Action<ISomeInterface>>(call, parameter);
myMock.Verify(expression);
}
推荐阅读
- python - 为什么这段代码中的 Scrapy Selector Xpath 结果总是 None ?
- sql-server - RHPAM WorkItemHandler 找不到数据库驱动程序
- javascript - JavaScript UTC 日期比较错误
- r - 每次出现非重复数字时将值增加一
- swift - 两种方式绑定到多个实例
- javascript - 当子组件更新时反应更新父级
- python - (Python)一系列布尔值中的等距真值
- python - AttributeError:“NoneType”对象没有属性“保存”[Flask 文件上传]
- kibana - Kibana KQL - 当参数值大于2时查找所有日志语句
- php - 提交表单后,如何获取在 ajax 错误消息中在服务器端处理的错误?