Должен ли я проверить, что методы НЕ вызываются? - PullRequest
2 голосов
/ 20 декабря 2011

Допустим, у меня есть этот код:

[HttpPost]
public ActionResult Edit(MyViewModel viewModel)
{
    if (ModelState.IsValid)
    {
        _myRepository.SaveStuff(viewModel.Property1, viewModel.Property2);
        return RedirectToAction("MyAction", "MyController");
    }
    else
    {
        return View("Edit", viewModel);
    }
}

Это ASP.NET MVC, но это на самом деле не имеет значения для моего вопроса.Суть в том, что метод (SaveStuff) вызывается только при выполнении требования.Теперь я хочу написать модульные тесты для этого метода ...

Я проверяю, что метод в хранилище вызывается, и RedirectToRoute возвращается, когда состояние модели допустимо.Я проверяю, что ViewResult возвращается, когда состояние модели недопустимо.

Мой вопрос таков: Должен ли я также написать тест, который проверяет, что метод в хранилище не вызванкогда состояние модели недействительно? Это хороший тест, чтобы убедиться, что я не получаю ненужные сохранения.Но я чувствую, что если я пойду по этому пути, проверяя, что ничего не происходит, количество тестов, которые я должен написать, очень сильно возрастет ...

Ответы [ 6 ]

4 голосов
/ 20 декабря 2011

Чтобы ответить на ваш вопрос, да. Вы должны обязательно проверить, что метод не вызывается, когда он не должен быть вызван. Вы определенно не хотите, чтобы ваше приложение сохраняло неверные данные.

Вы также правы, что количество тестов увеличится, если разбить все на отдельный тест. Ваши тесты могут иметь несколько утверждений. Я бы объединил два утверждения, когда состояние недействительно. Это избавит вас от написания почти идентичного теста.

4 голосов
/ 20 декабря 2011

Сколько существует путей через метод?

Не имеет ли смысла проверять их все?Было бы ошибкой сохранить его, если состояние модели недопустимо?

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

1 голос
/ 21 декабря 2011

Вы хотите проверить все пути кода.Если это действительно никогда не произойдет, тогда вам даже не нужно утверждение if, верно?Я ожидаю, что вы напишете два теста для этого метода:

// Note: I don't do .NET, so pardon any basic errors
// and hopefully the intent shows through.

[SetUp]
public void SetUp()
{
   repository = new MockWidgetRepository()
   controller = new WidgetController(repository);
}

[Test]
public void savesValidWidgets() 
{
   var result = controller.Edit(new ValidViewModel());
   Assert.IsTrue(repository.SaveWasCalled());
   Assert.AreEqual(typeof(RedirectResult), result.GetType());
}

Это первый случай, который вы упомянули.Второй, однако, будет похожим.

[Test]
public void InvalidWidgetsAreRedisplayed()
{
   var result = controller.Edit(new InvalidViewModel());
   Assert.AreEqual(typeof(ViewResult), result.GetType());
}

Надеюсь, что поможет!

Брэндон

1 голос
/ 20 декабря 2011

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

Мой ответ, как правило, будет: да, вы должны, но на самом деле решение о том, что тестировать, остается за вами. Вы должны проверить все, что вас беспокоит.

В этом случае добавляется только один тест. Это не должно добавить много.

0 голосов
/ 22 декабря 2011

Да, вы должны проверить, что _repository.SaveStuff не вызывается.На самом деле у вас есть четыре теста, которые вам нужно написать.

  1. , если ModelState.IsValid = SaveStuff
  2. , если Not ModelState.IsValid = не SaveStuff
  3. если ModelState.IsValid = return RedirectToAction
  4. если Not ModelState.IsValid = return View

Если, как указано в вашем вопросе, вы проверяете, что SaveStuff и RedirectAction вместе выбудет тест на хрупкость

0 голосов
/ 20 декабря 2011

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

Для каждого тестового случая убедитесь, что он приводит к правильной последовательности сохранений - что составляет точно одно сохранение (с правильными аргументами) для действительного случая и точно Ноль сохраняет для неправильного регистра.

Моя общая причина этого заключается в том, что по возможности лучше , а не иметь разные тестовые коды для каждого случая, когда тестируемый код обрабатывает по-разному. Если у вас разные тестовые данные, проходящие через один и тот же тестовый код, меньше вероятность того, что при написании тестового кода вы испортите тот же крайний случай, который вы испортили в коде приложения. Поэтому я стараюсь структурировать как можно больше тестов данной функции с помощью общего кода в форме «вставьте эти входные данные и убедитесь, что выходные данные и побочные эффекты соответствуют ожидаемым». Надеюсь, вы также получите меньше тестового кода, потому что вы систематически тестируете все побочные эффекты для всех входов, а не пишете отдельный код для каждого ввода.

Если вам действительно повезет, вы сможете добавлять регрессионные тесты и тесты новых функций в будущем, просто добавляя тестовые примеры, без написания какого-либо нового тестового кода вообще.

...