带参数的起订量 ReturnsAsync()

Posted

技术标签:

【中文标题】带参数的起订量 ReturnsAsync()【英文标题】:Moq ReturnsAsync() with parameters 【发布时间】:2015-10-10 05:15:17 【问题描述】:

我正在尝试像这样模拟存储库的方法

public async Task<WhitelistItem> GetByTypeValue(WhitelistType type, string value)

使用 Moq ReturnsAsync,如下所示:

static List<WhitelistItem> whitelist = new List<WhitelistItem>();

var whitelistRepositoryMock = new Mock<IWhitelistRepository>();

whitelistRepositoryMock.Setup(w => w.GetByTypeValue(It.IsAny<WhitelistType>(), It.IsAny<string>()))
                                    .ReturnsAsync((WhitelistType type, string value) =>
                                    
                                        return (from  item in whitelist
                                                where item.Type == type && item.Value == value
                                                select item).FirstOrDefault();
                                    );

但我在“... ReturnsAsync((WhitelistType type...):

无法将 lambda 表达式转换为类型“Model.WhitelistItem”,因为 它不是委托类型

WhitelistType 就是这样的枚举:

public enum WhitelistType
    
        UserName,
        PostalCode
    

我按小时搜索,但没有找到任何问题的答案。

有什么线索吗?

【问题讨论】:

【参考方案1】:

Moq v4.5.28 开始

您可以将 ReturnsAsync 与 lambdas 一起使用,就像问题的代码示例中一样。不再需要使用Task.FromResult()。您只需需要指定 lambda 委托参数的类型。否则你会得到同样的错误信息:

无法将 lambda 表达式转换为类型“Model.WhitelistItem”,因为它不是委托类型

举个例子,以下内容适用于最新版本的起订量:

whitelistRepositoryMock.Setup(w => w.GetByTypeValue(It.IsAny<WhitelistType>(), It.IsAny<string>()))
                                .ReturnsAsync((WhitelistType type, string value) =>
                                
                                    return (from  item in whitelist
                                            where item.Type == type && item.Value == value
                                            select item).FirstOrDefault();
                                );

Moq v4.5.28 之前(答案由Alexei Levenkov 提供)

您必须将ReturnsTask.FromResult 一起使用:

.Returns((WhitelistType type, string value) =>
 
     return Task.FromResult(
       (from  item in whitelist
           where item.Type == type && item.Value == value
           select item).FirstOrDefault()
       );
);

【讨论】:

这对你有用吗?我得到“无法将 lambda 表达式转换为类型 x,因为它不是委托类型”,即使在指定类型并完全像您一样执行之后也是如此。最新最小起订量 4.14 或其他东西【参考方案2】:

我知道这是一个老问题,但这里给出的一个答案对我不起作用,我能够弄清楚。似乎您必须将模拟函数的参数类型作为类型参数包含到ReturnsAsync() 首先,然后是模拟类类型,然后是返回类型。

例如:.ReturnsAsync&lt;T1, T2, TMock, TResult&gt;((arg1, arg2) =&gt; ... )

T1, T2 是模拟函数参数的类型,(arg1, arg2) 是调用模拟函数时给出的实际参数。

所以给定 OP 的代码,它看起来像这样:

whitelistRepositoryMock.Setup(w => w.GetByTypeValue(It.IsAny<WhitelistType>(), It.IsAny<string>()))
                       .ReturnsAsync<WhitelistType, string, IWhiteListRepository, WhitelistItem>((type, value) =>
                       
                            return (from  item in whitelist
                                    where item.Type == type && item.Value == value
                                    select item).FirstOrDefault();
                       );

编辑:我在前面的答案中稍后意识到,类型是在 lambda 中给出的,它确实有效。如果您像我一样省略类型,则不会。你必须使用我使用的表格。

【讨论】:

以上是关于带参数的起订量 ReturnsAsync()的主要内容,如果未能解决你的问题,请参考以下文章

无法为 MediatR 设置起订量回调

MOQ - 根据参数值(多个参数)设置方法

起订量 IServiceProvider / IServiceScope

起订量中 VerifyAll() 的用途是啥?

如何为起订量中的属性赋值?

使用最小起订量模拟静态属性