Я изо всех сил пытаюсь разобраться в модульном тестировании. Я следил за примерами как из ужина Nerd, так и из профессионального фреймворка asp.net MVC, но как только я попробую свой собственный, быстро застрял. В качестве теста я попытался создать класс проверки, который просто использует информацию для входа - имя пользователя и пароль для возврата пользователя из репозитория. Я использовал этот пример, так как довольно просто представить, какие тесты можно выполнить: Is_Password_Valid, Is_Username_Valid и т. Д.
Я слишком долго пытался понять это. Может ли кто-нибудь привести пример того, как они могут подойти к этому как к модульному тесту? Думаю, как только я раскрою это, я уйду.
//Arrange
string email = "test@test.com";
string password = "test";
//Arrange
List<Customer> customer = new List<Customer>();
customer.Add(new Customer { CustomerId = 1, Email = email, Password = "best", FirstName = "test", LastName = "wods", Sex = true });
mockRepos = new Moq.Mock<ICustomerRepository>();
mockRepos.Setup(x => x.GetCustomerByPasswordUsername(email, password)).Returns(customer.First());
Authenticate auth = new Authenticate(mockRepos.Object);
//Act
var result = auth.Login(email, password);
//Assert
//this is where I start to become unstuck??????
2 ответа
Похоже, вы на правильном пути, но позвольте мне попытаться объяснить, как бы я прошел тест.
Фактическая тестируемая система (SUT) - это Authenticate
класс. Вы мало что рассказали об этом, поэтому я предполагаю следующее:
Он использует экземпляр ICustomerRepository
для определения существования пользователя на основе комбинации имени пользователя (электронной почты) и пароля.
Когда репозиторий возвращает экземпляр Customer
, учитывая комбинацию имени пользователя и пароля, метод Login
возвращает true. Когда репозиторий возвращает null
, метод Login
возвращает false.
Я буду использовать эти предположения в дальнейшем, но если они неверны, я уверен, что вы сможете изменить тесты так, чтобы они имели смысл для вашего сценария.
Тест 1. Если комбинация имени пользователя и пароля верна, Login
вернет true
public void LoginWillReturnTrueForAValidUsernamePasswordCombination()
{
string email = "test@test.com";
string password = "test";
//Dummy customer
var customer = new Customer();
//Create mock
var mockRepos = new Moq.Mock<ICustomerRepository>();
mockRepos.Setup(x => x.GetCustomerByPasswordUsername(
It.Is<string>(s => s == email),
It.Is<string>(s => s == password))
.Returns(customer);
var auth = new Authenticate(mockRepos.Object);
//Act
var result = auth.Login(email, password);
//Assert
Assert.IsTrue(result);
}
Обратите внимание на использование It.Is
. По сути, макет настроен таким образом, что он будет возвращать фиктивный объект клиента только тогда, когда адрес электронной почты и пароль, определенные в вашем тесте, передаются методу GetCustomerByPasswordUsername
.
Тест 2. Если комбинация имени пользователя и пароля неверна, Login
вернет false
public void LoginWillReturnFalseForAnInvalidUsernamePasswordCombination()
{
string email = "test@test.com";
string password = "test";
//Create mock
var mockRepos = new Moq.Mock<ICustomerRepository>();
mockRepos.Setup(x => x.GetCustomerByPasswordUsername(
It.Is<string>(s => s == email),
It.Is<string>(s => s == password))
.Returns<Customer>(null);
var auth = new Authenticate(mockRepos.Object);
//Act
var result = auth.Login(email, password);
//Assert
Assert.IsFalse(result);
}
Несмотря на неявное тестирование с помощью вышеуказанных тестов, вы можете пойти дальше и написать тест, который гарантирует, что метод Login
передает правильные параметры в репозиторий. Такой тест мог бы выглядеть следующим образом:
Тест 3: при входе в репозиторий будет правильно запущен вход
public void LoginWillInvokeGetCustomerByPasswordUsernameCorrectly()
{
string email = "test@test.com";
string password = "test";
//Create mock
var mockRepos = new Moq.Mock<ICustomerRepository>();
mockRepos.Setup(x => x.GetCustomerByPasswordUsername(
It.Is<string>(s => s == email),
It.Is<string>(s => s == password))
.Returns<Customer>(null)
.Verifiable();
var auth = new Authenticate(mockRepos.Object);
//Act (ignore result. We are only testing correct invocation)
auth.Login(email, password);
//Assert
mockRepos.Verify();
}
Метод имитации Verify
генерирует исключение, если настроенные методы не были вызваны.
Надеюсь, это поможет. Не стесняйтесь спрашивать, есть ли у вас дополнительные вопросы.
Если у вас есть тестируемая система, которая использует API, к которому ваша SUT также добавляет слушателя, это также может стать немного сложнее (вы можете сделать то же самое с исполнителями и таймерами (имитируйте и то, и другое)).
class RealAPIYouSUTUses {
public void addListener(XXXListener l);
}
class MockAPI implements RealAPIYourSUTUses{
public void addListener(XXXListener l) {
this.cachedListener = l;
}
public XXXListener getListener() {
return cachedListener;
}
}
Затем ваш модульный тест может протестировать листезнер и его взаимодействие с системой ...
class Test {
public void test() {
MockAPI mockAPI = new MockAPI();
SUT sut = new SUT(mockAPI);
sut.doSomething();
//expect your listener to be added from calling doSomething....
XXXListener l = mockApi.getListener();
//simulate firing an event into your SUT
l.fireEvent(new Event("asdf"));
}
}
Самое интересное во всем этом то, что вы можете имитировать Executor.java и Timer.java, и ваш тест может захватить исполняемый файл, который был передан исполнителю, и TimerTaks для таймера, и вы можете запустить их в порядке и в обратном порядке, чтобы убедиться, что ваша система работает.
Я занимаюсь асинхронным программированием и модульным тестированием, как эта скала, чтобы вы могли убедиться, что интеграция между всеми вашими классами работает.
Похожие вопросы
Новые вопросы
unit-testing
Модульное тестирование - это метод, с помощью которого отдельные блоки исходного кода тестируются, чтобы определить, пригодны ли они для использования.