模拟 Func<> 的适当方式
Appropriate way to mock Func<>
嗨,我正在尝试模拟以下内容:
var result = _scope.Execute<FooService, IList<FooEntity>>(x => x.GetFooEntities(fooModel));
这就是我尝试模拟它的方式:
_mockedScope
.Setup(x => x.Execute<FooService, IList<FooEntity>>(f => f.GetFooEntities(It.IsAny<FooModel>())))
.Returns(new List<FooEntity>)
但是当我 运行 测试时它抛出一个异常
Unsupported expression: s => s.GetFooEntities(IsAny())
有什么建议可以模拟吗?
这是我想要最小起订量的例子
public class Test
{
private readonly IScope _scope;
public Test(IScope scope)
{
_scope = scope;
}
public void Foo()
{
var foo = new FooEntity();
Result<IList<Foo>> result =
_scope.Execute<FooService, IList<Foo>>(
"f",
s => s.GetFoo(foo));
}
}
public class Foo
{
}
public class FooEntity
{
}
public class FooService
{
public List<Foo> GetFoo(FooEntity f);
}
public interface IScope
{
Result<TResult> Execute<T1, TResult>(string temp, Func<T1, TResult> function);
}
public class Result<T>
{
private Result(T value, Exception exception)
{
Value = value;
Error = exception;
}
public Exception Error { get; }
public T Value { get; }
public bool HasError => Error != null;
public static Result<T> Fail(Exception exception) => new Result<T>(default(T), exception);
public static Result<T> Success(T value) => new Result<T>(value, null);
}
虽然最小起订量使用表达式来设置模拟,但您正在尝试模拟表达式。这对于最小起订量来说往往非常困难,但通过匹配的参数有解决方法。
假设 Scope.Execute
方法定义为
public interface IScope {
Result<TResult> Execute<T, TResult>(string temp, Func<T, TResult> function);
}
在设置依赖于表达式参数的模拟时,使用 It.IsAny
允许灵活性。
_mockedScope
.Setup(x => x.Execute<FooService, IList<Foo>>(It.IsAny<string>(), It.IsAny<Func<FooService, IList<Foo>>>()))
.Returns(Result<IList<Foo>>.Success(new List<Foo>()));
It.IsAny<Func<FooService, IList<Foo>>>()
将覆盖调用代码中的 s => s.GetFoo(foo)
。
给定
public class Test {
private readonly IScope _scope;
public Test(IScope scope) {
_scope = scope;
}
public IList<Foo> Foo() {
var foo = new FooEntity();
Result<IList<Foo>> result = _scope.Execute<FooService, IList<Foo>>("f", s => s.GetFoo(foo));
var value = result.Value;
return value;
}
}
下面的完整示例用于演示上面解释的内容
[TestClass]
public class ExpressionMock {
[TestMethod]
public void TestFoo() {
//Arrange
var _mockedScope = new Mock<IScope>();
_mockedScope
.Setup(x => x.Execute<FooService, IList<Foo>>(It.IsAny<string>(), It.IsAny<Func<FooService, IList<Foo>>>()))
.Returns(Result<IList<Foo>>.Success(new List<Foo>()));
var subject = new Test(_mockedScope.Object);
//Act
var actual = subject.Foo();
//Assert
actual.Should().NotBeNull();
}
}
参考Moq Quickstart以更好地了解如何使用该框架
嗨,我正在尝试模拟以下内容:
var result = _scope.Execute<FooService, IList<FooEntity>>(x => x.GetFooEntities(fooModel));
这就是我尝试模拟它的方式:
_mockedScope
.Setup(x => x.Execute<FooService, IList<FooEntity>>(f => f.GetFooEntities(It.IsAny<FooModel>())))
.Returns(new List<FooEntity>)
但是当我 运行 测试时它抛出一个异常
Unsupported expression: s => s.GetFooEntities(IsAny())
有什么建议可以模拟吗?
这是我想要最小起订量的例子
public class Test
{
private readonly IScope _scope;
public Test(IScope scope)
{
_scope = scope;
}
public void Foo()
{
var foo = new FooEntity();
Result<IList<Foo>> result =
_scope.Execute<FooService, IList<Foo>>(
"f",
s => s.GetFoo(foo));
}
}
public class Foo
{
}
public class FooEntity
{
}
public class FooService
{
public List<Foo> GetFoo(FooEntity f);
}
public interface IScope
{
Result<TResult> Execute<T1, TResult>(string temp, Func<T1, TResult> function);
}
public class Result<T>
{
private Result(T value, Exception exception)
{
Value = value;
Error = exception;
}
public Exception Error { get; }
public T Value { get; }
public bool HasError => Error != null;
public static Result<T> Fail(Exception exception) => new Result<T>(default(T), exception);
public static Result<T> Success(T value) => new Result<T>(value, null);
}
虽然最小起订量使用表达式来设置模拟,但您正在尝试模拟表达式。这对于最小起订量来说往往非常困难,但通过匹配的参数有解决方法。
假设 Scope.Execute
方法定义为
public interface IScope {
Result<TResult> Execute<T, TResult>(string temp, Func<T, TResult> function);
}
在设置依赖于表达式参数的模拟时,使用 It.IsAny
允许灵活性。
_mockedScope
.Setup(x => x.Execute<FooService, IList<Foo>>(It.IsAny<string>(), It.IsAny<Func<FooService, IList<Foo>>>()))
.Returns(Result<IList<Foo>>.Success(new List<Foo>()));
It.IsAny<Func<FooService, IList<Foo>>>()
将覆盖调用代码中的 s => s.GetFoo(foo)
。
给定
public class Test {
private readonly IScope _scope;
public Test(IScope scope) {
_scope = scope;
}
public IList<Foo> Foo() {
var foo = new FooEntity();
Result<IList<Foo>> result = _scope.Execute<FooService, IList<Foo>>("f", s => s.GetFoo(foo));
var value = result.Value;
return value;
}
}
下面的完整示例用于演示上面解释的内容
[TestClass]
public class ExpressionMock {
[TestMethod]
public void TestFoo() {
//Arrange
var _mockedScope = new Mock<IScope>();
_mockedScope
.Setup(x => x.Execute<FooService, IList<Foo>>(It.IsAny<string>(), It.IsAny<Func<FooService, IList<Foo>>>()))
.Returns(Result<IList<Foo>>.Success(new List<Foo>()));
var subject = new Test(_mockedScope.Object);
//Act
var actual = subject.Foo();
//Assert
actual.Should().NotBeNull();
}
}
参考Moq Quickstart以更好地了解如何使用该框架