【问题标题】:Verify method invocation with Expression giving exception使用给出异常的表达式验证方法调用
【发布时间】:2018-06-29 07:08:22
【问题描述】:

我正在尝试通过使用 Linq Expression methods Api 来使用 Moq 的 Verify 方法(以验证是否调用了方法)。

以下是两个单元测试。 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.
    }
  }
}

【问题讨论】:

  • 哪一行代码抛出异常?
  • 在TestMethod2中,myMock.Verify(expression) 抛出异常

标签: c# lambda expression moq verify


【解决方案1】:

第一个问题是您不能使用 Mock 的 .Object 作为类型的来源,因为它不是“正确”类型。最安全的方法是使用接口本身作为类型的来源。

第二个问题是您需要为 lambda 表达式指定一个参数,而这必须是您调用该方法的对象;就像你在测试 1 中所做的那样 m =&gt; 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);
    }

【讨论】:

  • 感谢 Richadissimo,解决方案有效,感谢您也很好地解释了这一点
猜你喜欢
  • 2011-10-02
  • 2019-07-15
  • 1970-01-01
  • 2012-03-03
  • 1970-01-01
  • 2011-03-08
  • 2016-05-05
  • 2015-01-21
  • 2011-03-12
相关资源
最近更新 更多