Moq возвращает Async() с параметрами

Я пытаюсь издеваться над способом хранилища

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

Невозможно преобразовать лямбда-выражение в тип "Model.WhitelistItem", поскольку оно не является типом делегата.

WhitelistType - это Enum, подобный этому:

public enum WhitelistType
    {
        UserName,
        PostalCode
    }

Я искал по часам и не нашел ответа на мою проблему.

Есть какие-нибудь подсказки?

2 ответа

Решение

ReturnsAsync не имеет лямбда-версию в отличие Returns один.

Исправить: использовать Returns с Task.FromResult

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

Принятый ответ устарел. Теперь вы можете использовать ReturnsAsync с лямбдами, точно так же, как в примере кода вопроса. Не нужно использовать Task.FromResult() больше Вам просто нужно указать типы аргументов лямбда-делегата. В противном случае вы получите то же сообщение об ошибке:

Невозможно преобразовать лямбда-выражение в тип "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();
                                });

Я знаю, что это старый вопрос, но один ответ, данный здесь, не сработал для меня, и я смог его понять. Кажется, вам нужно включить типы аргументов имитируемой функции в качестве параметров типа для 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();
                       });

Изменить: позже в предыдущем ответе я понял, что типы указаны в лямбде, которая действительно работает. Если вы не укажете типы, как это сделал я, этого не произойдет. Вам нужно будет использовать форму, которую использовал я.

Другие вопросы по тегам