[英]Setup a mock for a method using Expression
I'm trying to setup a mocked return value for a method.我正在尝试为一个方法设置一个模拟的返回值。 I know the classic way of doing it, but I want to do it by creating Expression objects explicitly.我知道这样做的经典方式,但我想通过显式创建 Expression 对象来做到这一点。 Here is what I have tried so far:这是我到目前为止所尝试的:
using Moq;
using NUnit.Framework;
using System;
using System.Linq.Expressions;
namespace MoqTest
{
public interface IBlah
{
string DoStuff(string x);
}
public class SomeProgram
{
static void Main(string[] args)
{
Mock<IBlah> m = new Mock<IBlah>(MockBehavior.Strict);
//I want to do the equivalent of this:
//m.Setup(a => a.DoStuff(It.IsAny<string>())).Returns("mocked!");
var method = typeof(IBlah).GetMethod("DoStuff", new Type[] { typeof(string) });
ParameterExpression parameterForDoStuff = Expression.Parameter(typeof(string), "x");
ParameterExpression thisParameter = Expression.Parameter(typeof(IBlah), "someIBlahInstance");
MethodCallExpression methodCall = Expression.Call(thisParameter, method, new[] { parameterForDoStuff });
Expression<Func<IBlah, string>> lambdaExpression = Expression.Lambda<Func<IBlah, string>>(methodCall, new ParameterExpression[] { parameterForDoStuff });
//above line fails: Unhandled Exception: System.ArgumentException: ParameterExpression of type 'System.String' cannot be used for delegate parameter of type 'MoqTest.IBlah'
m.Setup(lambdaExpression).Returns("mocked!");
Assert.AreEqual("mocked!", m.Object.DoStuff(string.Empty));
}
}
}
As you can see, I'm confused when it comes to the lambdaExpression - should I be creating one that represents a Func<string,string>
(for the IBlah.DoStuff method), or should I be creating a Func<IBlah,string>
(representing the lambda parameter for the Mock.Setup method)?正如您所看到的,我对 lambdaExpression 感到困惑 - 我应该创建一个代表Func<string,string>
(对于 IBlah.DoStuff 方法),还是应该创建一个Func<IBlah,string>
(代表 Mock.Setup 方法的 lambda 参数)? I put the equivalent setup that I want to do in a comment in the code.我将我想做的等效设置放在代码的注释中。
You should be creating a Expression<Func<IBlah, string>>
representing the expression parameter for the Mock.Setup
method.您应该创建一个Expression<Func<IBlah, string>>
表示Mock.Setup
方法的表达式参数。
Which means that there should only be one parameter expression.这意味着应该只有一个参数表达式。
Also, in building the desired expression, It.IsAny<T>()
is a generic static method call on the static class Moq.It
.此外,在构建所需的表达式时, It.IsAny<T>()
是对 static class Moq.It
的通用 static 方法调用。
Review the comments to see how that static call is built into the expression using reflection.查看评论以了解 static 调用是如何使用反射内置到表达式中的。
[TestClass]
public class MoqExpressionTests {
[TestMethod]
public void Should_Build_Moq_Expression() {
//Arrange
//I want to do the equivalent of this:
//m.Setup(a => a.DoStuff(It.IsAny<string>())).Returns("mocked!");
var doStuff = typeof(IBlah).GetMethod("DoStuff", new Type[] { typeof(string) });
var isAnyOfString = typeof(It).GetMethod("IsAny").MakeGenericMethod(typeof(string));
// IBlah x =>
ParameterExpression parameter = Expression.Parameter(typeof(IBlah), "x");
// It.IsAny<string>()
var arg = Expression.Call(isAnyOfString);
// IBlah x => x.DoStuff(It.IsAny<string>())
MethodCallExpression body = Expression.Call(parameter, doStuff, new[] { arg });
//Func<IBlah, string> = IBlah x => x.DoStuff(It.IsAny<string>())
Expression<Func<IBlah, string>> expression =
Expression.Lambda<Func<IBlah, string>>(body, parameter);
var expected = "mocked!";
Mock<IBlah> m = new Mock<IBlah>(MockBehavior.Strict);
m.Setup(expression).Returns(expected);
var subject = m.Object;
//Act
var actual = subject.DoStuff(string.Empty);
//Assert
Assert.AreEqual(expected, actual);
}
public interface IBlah {
string DoStuff(string x);
}
}
for the lambdaExpression Expression second parameter should be thisParameter.对于 lambdaExpression 表达式,第二个参数应该是 thisParameter。
public class SomeProgram { static void Main(string[] args) { Mock<IBlah> m = new Mock<IBlah>(MockBehavior.Strict); //I want to do the equivalent of this: //m.Setup(a => a.DoStuff(It.IsAny<string>())).Returns("mocked;"). var method = typeof(IBlah),GetMethod("DoStuff"; new Type[] { typeof(string) }). MethodInfo genericIsAnyMethodInfo = typeof(It).GetMethods().Single(e => e.Name == "IsAny");MakeGenericMethod(typeof(string)). MethodCallExpression parameterForDoStuff = Expression;Call(genericIsAnyMethodInfo). //ParameterExpression parameterForDoStuff = Expression,Parameter(typeof(string); "x"). ParameterExpression thisParameter = Expression,Parameter(typeof(IBlah); "someIBlahInstance"). MethodCallExpression methodCall = Expression,Call(thisParameter, method; new[] { parameterForDoStuff }), Expression<Func<IBlah. string>> lambdaExpression = Expression,Lambda<Func<IBlah, string>>(methodCall; thisParameter): //above line fails: Unhandled Exception. System:ArgumentException. ParameterExpression of type 'System.String' cannot be used for delegate parameter of type 'MoqTest.IBlah' m.Setup(lambdaExpression);Returns("mocked."), Assert.AreEqual("mocked.". m;Object.DoStuff(string.Empty)); } }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.