Тестирование действия контроллера MVC с помощью ActionFilterAttribute

Общеизвестным преимуществом MVC является его пригодность для разработки через тестирование (TDD), поскольку вы можете напрямую вызывать действия контроллера из методов тестирования.

Как вы можете протестировать комбинацию действия контроллера с атрибутом ActionFilter (используя OnActionExecuted для изменения ActionResult, возвращаемого действием)? Если я просто вызываю действие, оно возвращает ActionResult из действия, но атрибут фильтра никогда не вызывается. Я думаю, что, возможно, вы можете получить это к Controller.ActionInvoker.InvokeAction(controllerContext, "ActionName"), но вам нужно точно имитировать так много контекста контроллера, чтобы заставить его работать, что это настоящая боль.

Кто-нибудь успешно сделал это?


person Dave Hanna    schedule 22.01.2010    source источник


Ответы (4)


Модульное тестирование касается отдельных модулей, а не их комбинации.

Модульные тесты предназначены для тестирования одной единицы функциональности/процесса/работы. Вы должны протестировать атрибут отдельно от действия контроллера.

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

  2. Затем проверьте, что ваш атрибут делает то, что должен = преобразовывать результаты действий, как ожидалось.

Два отдельных модульных теста, а не один.

person Robert Koritnik    schedule 22.01.2010
comment
+1 ... но я бы также проверил, что у вашего действия контроллера есть этот атрибут, как сказал Антон. - person Mark; 22.01.2010
comment
Фильтры действий — это отдельный код, который не требуется для действий контроллера. Я полагаю, что проверка того, что определенные действия контроллера имеют присоединенные к ним атрибуты, является скорее частью интеграционного тестирования, чем модульного тестирования. - person Robert Koritnik; 22.01.2010
comment
Я согласен, что вам не нужно выполнять этот код для тестирования контроллера, но если у вас есть требование, в котором говорится, что это действие должно быть зарегистрировано, вы проверяете, что это требование выполняется наличием этого действия.... не что действие на самом деле делает то, о чем говорит. - person Mark; 22.01.2010
comment
@Mark: я полностью понимаю, что вы имеете в виду, и я, вероятно, сделал бы это таким же образом и включил бы его в свой сценарий модульного тестирования, но ведение журнала само по себе является вопросом интеграции. Потому что журнал обычно является отдельной системой (как и БД), и это замедлит модульные тесты. Модульные тесты должны быть очень быстрыми. Как бы вы утверждали, что определенное сообщение журнала все равно было зарегистрировано? - person Robert Koritnik; 23.01.2010
comment
Предполагая, что добавленный нами фильтр действий просто регистрирует каждый раз, когда вызывается действие (просто пример произвольного фильтра действий), мы бы утверждали, что метод действия был связан с правильным действием. Затем у нас будет отдельная батарея тестов вокруг этого действия, которое называется правильными абстракциями ведения журнала. Затем у нас есть реализации этих абстракций журналирования, которые тестируются, чтобы убедиться, что они делают то, что делают. ... но при тестировании контроллера в БД ничего не регистрируется. - person Mark; 25.01.2010

Я думаю, вам будет лучше тестировать контроллер и атрибут (фильтр) изолированно, а затем утверждать, что действительно есть атрибут для конкретного действия (метода) контроллера.

person Anton Gogolev    schedule 22.01.2010
comment
+1 за тестирование каждого по отдельности, а затем утверждение, что действие имеет атрибут. - person Mark; 22.01.2010
comment
Как вы проверяете, правильно ли действие имеет определенный атрибут? - person Mike Cole; 08.01.2014

Мы делаем что-то подобное, когда проверяем наши проверки DataAnnotation. Мы проверяем модель свойств на наличие правильных атрибутов с помощью отражения. Когда мы тестируем наши контроллеры, мы просто устанавливаем достоверность модели вручную. Как упоминают Роберт и Антон, ваш тест должен выставлять одно конкретное утверждение для одного конкретного класса.

person Mark    schedule 22.01.2010

Как насчет фильтров, помогающих контексту, в котором выполняется действие? например, фильтр, создающий сеанс nhibernate? Мне нужно будет создать это в любом тесте? но в этом вся идея с фильтром!

person ivos    schedule 05.01.2011