Ответ зависит от того, что вы пытаетесь проверить.Пример звучит как что-то из огурца, но вы использовали термин BDD.Я связываю BDD с модульным тестированием снизу вверх.Если это так, предположим, что у вас есть некоторый класс аутентификации и пользовательский класс.
Класс пользователя:
public class User : IUser
{
public int ID { get; set; }
public string Name { get; set; }
public string Password { get; set; }
}
public interface IUser
{
int ID { get; }
string Name { get; }
string Password { get; }
}
Класс аутентификатора:
public class Authenticator : IAuthenticator
{
public Authenticator()
{
//Initialize and acquire some authentication mechanism (db, service, file, etc..)
}
public bool IsLoggedIn(IUser user)
{
return true;
}
public bool LoginUser(IUser user)
{
//Do real login.
return true;
}
public bool LogoutUser(IUser user)
{
//Do real logout.
return true;
}
}
public interface IAuthenticator
{
bool LoginUser(IUser user);
bool LogoutUser(IUser user);
}
Класс UserActions для вызова аутентификатора, управления разрешениями и т. Д .:
public class UserActions
{
private readonly IAuthenticator _authenticator;
private readonly IUser _user;
//private Permissions Permissions;
public UserActions(IUser user)
: this(new Authenticator(), user)
{ }
public UserActions(IAuthenticator authenticator, IUser user)
{
_authenticator = authenticator;
_user = user;
}
public bool Login()
{
var result = _authenticator.LoginUser(_user);
return result;
}
public void Logout()
{
_authenticator.LogoutUser(_user);
}
}
С этими классами я бы попытался проверить поведение (используя NUnit и MOQ) класса UserActions в отношении входа в систему ивыход из системыВ этом примере никакая работа не выполняется, но для примера представьте себе более полную реализацию:
[TestFixture]
public class Tester
{
[Test]
public void CanLoginGoodUser()
{
IUser user = new User { ID = 1, Name = "Test1", Password = "good" };
var authenticator = new Mock<IAuthenticator>();
authenticator.Setup(a => a.LoginUser(user)).Returns(true);
var action = new UserActions(authenticator.Object, user);
action.Login();
authenticator.Verify(a => a.LoginUser(It.Is<IUser>(u => u == user)), Times.AtLeastOnce());
}
[Test]
public void WontLoginBadUser()
{
IUser user = new User { ID = 1, Name = "Test1", Password = "bad" };
var authenticator = new Mock<IAuthenticator>();
authenticator.Setup(a => a.LoginUser(user)).Returns(false);
var action = new UserActions(authenticator.Object, user);
action.Login();
authenticator.Verify(a => a.LoginUser(It.Is<IUser>(u => u == user)), Times.AtLeastOnce());
}
}
На самом деле я не выполняю вход или выход из системы.Что я делаю, так это использую интерфейс для предоставления готовых ответов, которые показывают, как класс ведет себя, когда он взаимодействует с классами, которые он использует.В этом случае это объекты аутентификатора и пользователя.Обратите внимание, что я не издевался над классом пользователя, потому что на данный момент в этом нет необходимости.
Я уверен, что другие люди не согласятся с этим подходом, но это то, чем я сейчас занимаюсь.Он хорошо работает для меня в том смысле, что он позволяет проводить тестирование по принципу «снизу вверх», охват кода и проблемы разделения при разработке моего класса.