Moq使用参数

时间:2015-07-20 22:28:27

标签: c# unit-testing moq

我试图模仿存储库的方法

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

但是我在行中收到此错误&#34; ... ReturnsAsync((WhitelistType type ...):

  

无法将lambda表达式转换为&#39; Model.WhitelistItem&#39;因为   它不是委托类型

WhitelistType是这样的枚举:

public enum WhitelistType
    {
        UserName,
        PostalCode
    }

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

任何线索?

2 个答案:

答案 0 :(得分:17)

Moq v4.5.28起

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

  

由于Lambda表达式不是委托类型,因此无法将其转换为“ Model.WhitelistItem”类型

举个例子,以下适用于最新版本的Moq:

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

答案 1 :(得分:2)

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

例如:.ReturnsAsync<T1, T2, TMock, TResult>((arg1, arg2) => { ... } )

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中给出的。如果像我一样省略类型,就不会。您将必须使用我使用的表格。