【问题标题】:Moq - Setup Method with Expression of anonymous typeMoq - 具有匿名类型表达式的设置方法
【发布时间】:2020-06-06 20:42:42
【问题描述】:

我有一个带有这个签名的函数 -

TSelect Get<TSelect>(int id, Expression<Func<T, TSelect>> select);

T 在类级别上声明。这意味着允许开发人员传递他们希望对象返回的形状,例如 Linq 中的.Select

所以它的用法看起来像

_query.Get(123, x => new { x.Id, x.Name })

我不知道如何在 Moq 中进行设置。我已经看到很多关于使用It.IsAnyType 的答案,但这似乎不适用于表达式。而且 Moq 在设计上没有将匿名类型与对象匹配,因此 Expression&lt;Func&lt;MyType, object&gt;&gt; 不起作用。

有什么想法吗?

【问题讨论】:

  • 你能解释一下你到底想模拟什么吗?想象一下,嘲笑是有效的,你能添加一个伪代码来让你的问题更清楚吗?我不确定您是否正在尝试制作模拟表达式,模拟给定类型 TGet 函数等。

标签: c# generics moq


【解决方案1】:

如果您的目标是模拟一个返回匿名类型实例的select 函数,您可以通过辅助函数来实现:

public class MyUnitTest
{
    [Fact]
    public void Test()
    {
        var query = CreateMockQuery(
            new Person { Name = "Bob" },
            new { Id = default(int), Name = default(string) } // Declares the anonymous type
        );

        var result = query.Get(5, p => new { Id = 5, p.Name });
        Assert.Equal("Bob", result.Name);
    }

    private IQuery<T> CreateMockQuery<T, TSelect>(
        T source,
        TSelect _ /* captures the anonymous type*/)
    {
        var mockQuery = new Mock<IQuery<T>>();
        mockQuery
            .Setup(x => x.Get(It.IsAny<int>(), It.IsAny<Expression<Func<T, TSelect>>>()))
            .Returns(
                (int id, Expression<Func<T, TSelect>> select)
                    => select.Compile()(source));
        return mockQuery.Object;
    }
}

public class Person
{
    public string Name { get; set; }
}

public interface IQuery<T>
{
    TSelect Get<TSelect>(int id, Expression<Func<T, TSelect>> select);
}

为避免将匿名类型作为泛型类型参数传递,我们可以将其作为输入传递给CreateMockQuery,以便编译器自动检测类型。

【讨论】:

    猜你喜欢
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-22
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 2014-01-28
    相关资源
    最近更新 更多