Moq Модульное тестирование — как я могу передать действие своему классу, чтобы проверить, вызывается ли это действие?

#c# #unit-testing #action #moq #invoke

#c# #модульное тестирование #Экшен #moq #вызвать

Вопрос:

В принципе, у меня есть метод в моем классе, который вызывает Action<T> , если выполняются определенные условия. Как я могу выполнить модульное тестирование, чтобы убедиться, что действие вызвано?

 public class MyClass<T>
{
    private IDBService _dbService;

    private Action<T> _action;

    public MyClass(IDBService dbService, Action<T> action)
    {
        if (dbService == null) throw new ArgumentNullException("dbService");
        if (action == null) throw new ArgumentNullException("action");

        _dbService = dbService;
        _action = action;
    }

    public void CallActionIfPossible(T param)
    {
        if (_dbService.IsTopUser)
            action(param);
    }
}
  

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

1. Покажите нам свой текущий код, чтобы мы могли создать ответ?

Ответ №1:

Ну, основная идея заключается в том, что где-то Action<T> происходит какое-то изменение состояния (если этого не происходит, какой смысл?). Итак, модульный тест показывает, что ожидаемое изменение состояния происходит при выполнении условий, и что ожидаемое изменение состояния не происходит, когда условия не выполняются.

Конечно, в идеале вы издеваетесь над Action<T> тем, чтобы тестирование состояния было очень простым. Для этого вам не нужен Moq или любой другой фреймворк-макет:

 bool actionWasInvoked = false;
Action<Foo> action = foo => actionWasInvoked = true;
Bar<Foo> bar = new Bar<Foo>();
// set up conditions that should guarantee action is invoked
bar.M(action);
Assert.IsTrue(actionWasInvoked);
  

и

 bool actionWasInvoked = false;
Action<Foo> action = foo => actionWasInvoked = true;
Bar<Foo> bar = new Bar<Foo>();
// set up conditions that should guarantee action is NOT invoked
bar.M(action);
Assert.IsFalse(actionWasInvoked);
  

Конечно, я не знаю вашей точной настройки. Может быть, вы переходите к action построению Bar , или, может быть, у вас есть какой-то другой способ настройки действия. Но идея должна быть ясна.

Ответ №2:

Ответ Джейсона хорош, но одно предостережение, которое часто упускается из виду, заключается в том, что вам часто нужно будет проверять определенное количество вызовов (например, оно не только было вызвано, но и было вызвано ровно один раз). Поэтому я часто делаю что-то вроде этого:

 var callCount = 0;
Action<Foo> action = _ => callCount  ;
Bar<Foo> bar = new Bar<Foo>();
// set up conditions that should guarantee action is invoked
bar.M(action);
Assert.That(callCount, Is.EqualTo(1));
  

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

1. 1 Мне нравится идея, стоящая за этим (убедитесь, что у него есть необходимое количество вызовов).