Метод настройки с использованием массива параметров

#c# #nunit #moq

#c# #nunit #moq

Вопрос:

Я разрабатываю тесты для приложения. Существует метод, который имеет params массив в качестве параметра. Я настроил метод с использованием Moq, но когда я запускаю тест, возвращаемое значение метода равно null, что означает, что он не издевается.

Вот пример кода:

 public interface ITicketManager {
    string GetFirstTicketInQueueIfMatches(params string[] ticketsToMatch);
}

public class TicketManager : ITicketManager {
    private Queue<string> ticketQueue = new Queue<string>();

    public string GetFirstTicketInQueueIfMatches(params string[] ticketsToMatch) {
        var firstQueuedTicket = ticketQueue.Peek();
        var firstQueuedTicketMatchesAnyOfRequested = ticketsToMatch.Any(t => t == firstQueuedTicket);

        if(firstQueuedTicketMatchesAnyOfRequested)
            return firstQueuedTicket;

        return null;
    }
}
 

Макет кода выглядит следующим образом:

 var mock = new Mock<ITicketManager>();

mock.Setup(m => m.GetFirstTicketInQueueIfMatches(It.IsAny<string>()))
    .Returns(p => { 
    if(p.Contains("A"))
            return "A";

    return null;
});
 

Почему он никогда не попадает в издевательский метод?

Ответ №1:

Вы пытаетесь вызвать метод, принимающий одну строку, а не массив. Имейте в виду, что именно компилятор C # обрабатывает эту params часть, преобразуя вызывающий код, который просто указывает отдельные значения, в вызов, передаваемый в массиве. Что касается самого метода, то он просто получает массив — и это то, над чем вы издеваетесь.

Компилятор фактически превращает ваш код в:

 mock.Setup(m => m.GetFirstTicketInQueueIfMatches
                        (new string[] { It.IsAny<string>() }))
 

это не то, что вы хотите.

Вы должны использовать:

 mock.Setup(m => m.GetFirstTicketInQueueIfMatches(It.IsAny<string[]>()))
 

Если вам нужно убедиться, что ему присваивается только одно значение, вам нужно будет сделать это так же, как и для параметра, отличного от params.

По сути, params это имеет значение только для компилятора C #, а не для moq .

Комментарии:

1. @DiegoAC: Ну, у вас все равно есть условный возврат null . Вы пробовали заставить его возвращать «Foo» вместо этого, если p не содержит "A" ? Таким образом, вы, по крайней мере, увидите, что он вызывается…

2. Отличный ответ, Джон. Спасибо. На самом деле я получал только одну строку. Объяснение о компиляторе было очень полезным.

Ответ №2:

Я считаю params string , что должно быть сопоставлено, It.IsAny<string[]>() а не It.IsAny<string>()

Ответ №3:

Используя Moq, приведенный ниже код работает для настройки обратного вызова метода с аргументом params. Определение второго аргумента как массива делает трюк.

         MockLogger
            .Setup(x => x.Info(It.IsAny<string>(), It.IsAny<object[]>()))
            .Callback<string, object[]>((x, y) => _length = x.Length);