Зачем вам писать юнит-тесты для контроллеров?

22

Для меня это абсолютно неуместный юнит-тест, и я не понимаю, почему кто-то потратил время на его написание, потому что от него очень мало пользы. Я бы прекрасно знал, вернул ли этот контроллер искомый тип, выполнив метод в браузере. В самом деле, вы считаете, что для этого нужен тест и почему?

public class ConstituencyControllerTests
{
    private ConstituencyController _constituencyController;
    private Mock<IConstituencyService> _IConstituencyServiceMock;

    public ConstituencyControllerTests() {
        _IConstituencyServiceMock = new Mock<IConstituencyService>();
    }

    [Test]
    public async Task I_Check_For_Return_Type_And_Result() {
        _constituencyController = new ConstituencyController( _IConstituencyServiceMock.Object );

        var result = await _constituencyController.Get();
        var content = ( (dynamic)result ).Content;

        Assert.IsEmpty( content );
        Assert.IsInstanceOf( typeof( System.Web.Http.Results.OkNegotiatedContentResult<IEnumerable<ListOfConstituencies>> ), result );
        _IConstituencyServiceMock.Verify( x => x.ListOfConstituencies(), Times.Once() );
    }
}
глазурь
источник
7
Не согласен с этим @gnat. Речь идет не обязательно о языковых конструкциях, а о типе результата, возвращаемого контроллером. Хотя он может сводиться к тому же самому, когда у вас нет иерархии наследования, он становится совершенно другим зверем, когда контроллер ожидает возвращения Ancestors, контроллер возвращает Person, и теперь Person изменяется, чтобы происходить не от Ancestor, а от PeopleAncestor. ... также отвечает, почему тестирование такого метода может быть хорошей идеей ...;) Модульные тесты предназначены для выявления ситуаций, когда изменение одной вещи c / может сломать что-то другое.
Марьян Венема
Скорее всего, я не трачу много времени на модульное тестирование точек входа приложения. Это похоже на модульное тестирование основного метода консольного приложения. просто имеет для меня очень мало смысла.
Mvision

Ответы:

29

Ключевой момент здесь:

Я бы прекрасно знал, вернул ли этот контроллер искомый тип, выполнив метод в браузере.

Юнит-тестирование - это автоматизация нерегрессионного тестирования простых блоков кода, а не того, что вы смотрите сами. Вы не хотите делать себе всегда юнит-тестирование в своем приложении.

РЕДАКТИРОВАТЬ: Добавление комментария @anotherdave:

Речь идет о легкости масштабирования. Тестирование одного контроллера в браузере может быть в порядке; как насчет 10, 20, 50 контроллеров? Вы напишите тест один раз; вам может потребоваться обновить его, когда вы меняете контроллер, что накладные расходы. Но как часто вы развертываете? Конечно, ручная проверка каждый раз, когда есть намного больше накладных расходов, чем тест

В качестве альтернативы ответу @ Vladislav , модульное тестирование абсолютно всего может быть излишним, и действительно нежелательным. Если вам нужно что-то более легкое, вы можете провести нерегрессионное тестирование более высокого уровня с помощью Selenium. Конечно, вы получите меньшее покрытие, чем модульное тестирование, но вы можете получить приемлемое покрытие, которое стоит меньше времени на юнит-тестирование и является более гибким.

То есть, если вы все юнит-тестируете, вам нужно обновлять один или несколько тестов каждый раз, когда вы изменяете простой элемент.

Walfrat
источник
4
Также добавим re: I would know perfectly well if this controller returned the wanted type by executing the method in a browser.- это про легкость масштабирования. Тестирование одного контроллера в браузере может быть в порядке; как насчет 10, 20, 50 контроллеров? Вы напишите тест один раз; вам может потребоваться обновить его, когда вы меняете контроллер, что накладные расходы. Но как часто вы развертываете ? Конечно, ручная проверка каждый раз приводит к гораздо большим накладным расходам, чем тест.
anotherdave
«Модульное тестирование - это автоматизация» - правильно, но также и интеграционное тестирование (Selenium / Webdriver / и т. Д.). Я не думаю, что это так уж необходимо, чтобы модульные тесты выполнялись быстрее, чем интеграционные тесты. Многое зависит от подхода, однако, если для получения эффективного модульного теста требуется макетирование дюжины различных сервисов и вызовов, сделанных в каждый из них, интеграционный тест может быть быстрее реализован и проще в обслуживании (хотя, как правило, намного медленнее, да) , Дело в том, что многое зависит от контекста и сложности тестируемого кода.
Аромат
Добавлен комментарий @anotherdave
Walfrat
@ Моя точка зрения была противоположной: полное модульное тестирование кода - это то, что отнимает много времени и делает код очень сложным для изменения без необходимости какого-либо модульного теста. Интеграционный тест легче. Конечно, вы хотите, чтобы модульное тестирование было чем-то очень сложным, но не потому, что вы тестировали этот компонент, вам нужно все тестировать. Еще раз мы видим людей, ищущих серебряную пулю там, где его нет.
Вальфрат
24

Зачем вам писать юнит-тесты для контроллеров?

Потому что, не зная контекста, вы не можете точно сказать, нужно ли вам проверять то или иное. Вот несколько причин, почему вы можете захотеть протестировать контроллеры:

  • Контроллер может содержать сложную сервисную логику, которая подвержена ошибкам. Сами сервисы могут работать нормально, это результат, который вы хотите протестировать, и по какой-то причине вы решили не добавлять оркестровочный слой в свое приложение.
  • ваши контроллеры содержат ВЕСЬ бизнес-логику приложения, и контроллеры - это фактически все, что вы МОЖЕТЕ протестировать (пожалуйста, не делайте вид, что всю свою жизнь вы работали с идеальными кодовыми базами, такие программы есть, поверьте мне)
  • ваша команда состоит из 99% гениев и 1% средних людей, и вы хотите, чтобы этот 1% от ошибок в их зарплате
Владислав Раструсный
источник
2
Я бы добавил: «Вы не можете предвидеть, кто в будущем собирается избавиться от проекта, и тесты являются частью самодокументированного кода»
Laiv
4
В середине, проект, который был создан без тестирования, может не быть тестируемым каким-либо другим способом, кроме тестирования контроллера без макетов. Я работаю с командой C #, которая занимается именно таким проектом, поэтому они пишут тесты контроллеров до тех пор, пока не смогут добавить необходимую структуру (интерфейсы и т. Д.) Для более детального тестирования.
Уэйн Конрад
1

Я полностью согласен с ОП.

Модульный тест для контроллера не имеет смысла. Вы неявно тестируете свои контроллеры с помощью регрессионных тестов (например, с помощью Selenium).

Вы должны TDD все компоненты / объекты, которые использует контроллер, и поддерживать контроллеры как можно более тонкими. Тогда все правильно проверено модулем. В чем вы хотите убедиться, так это в том, что все хорошо работает вместе при выполнении веб-запросов. Это регрессионное тестирование.

winkbrace
источник
Может быть и так, но это не ответ на вопрос. Фактически, это аргумент против использования модульных тестов здесь.
JᴀʏMᴇᴇ
Я думаю, что ответил на вопрос "Как вы считаете, нужен ли для этого тест и почему?"
winkbrace
Да, я думаю, что @winkbrace и у меня одни и те же мысли по этому поводу. Но я также считаю, что это дискуссия о том, что вы должны модульный тест, а не. Я думаю, что люди слишком много испытывают и "неправильные" вещи. в моем примере тестирование контроллера дает очень мало пользы, так как он такой тонкий и, надеюсь, имеет тесты, окружающие сервисы. Все ответы здесь имеют смысл и имеют хорошие моменты, но на самом деле невозможно пометить один как правильный ответ.
глазурь
Логика контроллера может быть проверена с использованием автоматических интеграционных тестов, отдельных и отличных от модульных тестов для отдельных компонентов.
KevBurnsJr
-1: модульный тест для контроллера может быть бессмысленным. Контроллеры имеют дело с преобразованием, но иногда само преобразование является сложным, и разработчик может захотеть покрыть его. Я также думаю, что модульные тесты 1) в конечном итоге предназначены для проверки реализации, не обязательно для проверки поведения высокого уровня, и 2) должны быть чертовски быстрыми . Оба качества делают юнит-тесты гораздо более полезными во время реализации; Другими словами, они в конечном итоге являются инструментом разработчика и, кстати, способом проверки качества продукта.
rsenna