模拟Func<>的适当方法

时间:2018-02-12 10:10:43

标签: c# unit-testing mocking moq xunit

您好我正在尝试嘲笑以下内容:

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>)

但是当我运行测试时,它会抛出异常

  

不支持的表达式:s =&gt; s.GetFooEntities(IsAny())

有什么建议我怎么嘲笑它?

以下是我想要moq的例子

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);
}

1 个答案:

答案 0 :(得分:1)

虽然moq使用表达式来设置模拟,但您正在尝试模拟表达式。对于Moq来说,这往往非常困难,但是通过匹配的参数可以找到解决方法。

假设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以更好地理解如何使用框架

相关问题