Ответ 1
Контекст выглядит хорошо. Мне нравится, как вы разрешили конфликтующий It
с псевдонимами. Я бы сказал, что псевдоним Moq можно улучшить. Рассмотрим что-то вроде фразы. Например, Param.Is<T>
или Value.Is<T>
.
Некоторые заметки с фрагментами кода, затем весь текст переписан внизу.
Сценарий - это ваш Subject
Тема может быть сценарием из истории. Кроме того, он получает визуализацию с вашим тестовым прогоном (особенно хорошо в отчете HTML).
[Subject("Login Page")]
Не тратьте время на "С" именованные базовые классы
Создатель MSpec, Аарон Йенсен, вернул из синтаксиса "С" вообще. Имена классов контекста не отображаются для каких-либо отчетов, поэтому не тратьте время на создание значимого имени.
public abstract class MembershipContext
Данное заданное имя класса спецификации
Назовите конкретный класс спецификаций после данного в вашей истории. Тем более, что имя базового класса нигде не сообщается, вы можете потерять половину своего контекста в отчете! Также не следует помещать имя тестируемой системы в имена классов контекста. Это упрощает ваши контексты для реорганизации тестируемой системы.
public class When_an_existing_user_enters_valid_credentials
Базовые классы классов должны содержать только общую инициализацию
И часто не нужны. Они приводят к разделению фаз Arrange и Act. Используйте базовый класс для обычной инициализации поля, например, для настройки смежных зависимостей. Но вы не должны издеваться над поведением в базовом классе. И вы не должны помещать контекстно-зависимую информацию в базовый класс. В вашем примере, имя пользователя/пароль. Таким образом, вы можете создать второй контекст с недопустимыми учетными данными.
Establish context = () =>
{
membership = new Mock<ISiteMembership>();
loginController = new LoginController(membership.Object);
};
Поля в конкретном классе спецификации должны быть закрытыми
Это уменьшает "церемонию" языка в вашем тесте. Вы должны разместить их ниже всех специальных делегатов MSpec, поскольку те части спецификации отображают большую часть истории.
static ActionResult result;
Капитальный ремонт спецификации
Спецификация здесь является прекрасным примером установления глобального контекста MembershipContext
и наследования его в контексте, специфичном для спецификации (таким образом, дополнительный Establish
).
[Subject("Login Page")]
public class When_an_existing_user_enters_valid_credentials : MembershipContext
{
Establish context = () =>
{
membership
.Setup<bool>(m => m.Validate(
Param.Is<string>(s => s == username),
Param.Is<string>(s => s == password)))
.Returns(true);
};
Because of = () => result = loginController.Login(username, password);
It should_log_the_user_in;
It should_redirect_the_user_to_the_admin_panel;
It should_show_message_confirming_successful_login;
static ActionResult result;
const string username = "username";
const string password = "password";
}
public abstract class MembershipContext
{
Establish context = () =>
{
membership = new Mock<ISiteMembership>();
loginController = new LoginController(membership.Object);
};
protected static Mock<ISiteMembership> membership;
protected static LoginController loginController;
}