Я пишу тестовый сценарий для своего Пользовательского элемента управления, который запросит использование MessageBox. Шоу Пользовательского Действия, просящего обработать или Отменить операцию. Как я могу разработать свой модульный тест для имитации Взаимодействия с пользователем для продолжения?.
Я не хочу осуществлять рефакторинг для перемещения логики в средний уровень. Это - простой случай получения Пользовательского Согласия и продолжения вызова среднего уровня. Любая справка/идеи, реструктурирующая UI для этого сценария, также будет полезна.
Нажатие кнопки есть не что иное, как вызов соответствующего события click
. Так что вы можете построить свой тест на этом.
Еще лучше (если это еще не так) переместить свой код из внешнего интерфейса и построить свои модульные тесты на основе бизнес-действий, в противном случае вы бы вызывали их нажатием кнопки.
update after edit by author
У вас не получится заставить это работать, пока вы не готовы разбивать вещи, вы не можете строить свои модульные тесты на основе «щелкните здесь», «щелкните там». Представьте себе следующий код:
private int MyFunction()
{
bool insideVariable = false;
if(insideVariable)
return 1;
else
return 2;
}
Вы никогда не сможете выполнить модульное тестирование в случае, когда для параметра insideVariable установлено значение true; Вы также можете:
return 1
находился где-то на среднем уровне. return 1
был методом в вашем графическом интерфейсе. Затем вы можете протестировать эту функцию. Интерфейсы приложений должны быть легко заменены, поэтому бизнес-логика не должна храниться там. Модульные тесты - это просто еще один интерфейс, живущий рядом с вашим основным графическим интерфейсом.
Предоставить решение было бы намного проще с помощью опубликованного метода пользовательского интерфейса или связанных методов. Также просмотр TestMethod (ов) может помочь даже неполным методам.
Если я понимаю, что цель вашего теста - определить, что происходит при различных возможностях щелчка?
Вы можете настроить свой фактический метод, который запускает MessageBox
, используя Инверсия управления и Внедрение зависимостей , например:
public class ClassUnderTest
{
private static Func<string, string, MessageBoxButtons, DialogResult>
_messageBoxLocator = MessageBox.Show;
public static Func<string, string, MessageBoxButtons, DialogResult>
MessageBoxDependency
{
get { return _messageBoxLocator; }
set { _messageBoxLocator = value; }
}
private void MyMethodOld(object sender, EventArgs e)
{
if (MessageBox.Show("test", "", MessageBoxButtons.YesNo) ==
System.Windows.Forms.DialogResult.Yes)
{
//Yes code
AnsweredYes = true;
}
else
{
//No code
}
}
public bool AnsweredYes = false;
public void MyMethod(object sender, EventArgs e)
{
if (MessageBoxDependency(
"testText", "testCaption", MessageBoxButtons.YesNo)
==
System.Windows.Forms.DialogResult.Yes)
{
//proceed code
AnsweredYes = true;
}
else
{
//abort code
}
}
}
, а затем метод тестирования (не забудьте включить с помощью Microsoft.VisualStudio.TestTools.UnitTesting;
вверху) будет выглядеть следующим образом:
[TestMethod]
public void ClassUnderTest_DefaultAnsweredYes_IsFalse()
{
var classUnderTest = new ClassUnderTest();
Assert.AreEqual(false, classUnderTest.AnsweredYes);
}
[TestMethod]
public void MyMethod_UserAnswersYes_AnsweredYesIsTrue()
{
//Test Setup
Func<string, string, MessageBoxButtons, DialogResult>
fakeMessageBoxfunction =
(text, caption, buttons) =>
DialogResult.Yes;
//Create an instance of the class you are testing
var classUnderTest = new Testing.ClassUnderTest();
var oldDependency = Testing.ClassUnderTest.MessageBoxDependency;
Testing.ClassUnderTest.MessageBoxDependency = fakeMessageBoxfunction;
try
{
classUnderTest.MyMethod(null, null);
Assert.AreEqual(true, classUnderTest.AnsweredYes);
//Assert What are you trying to test?
}
finally
{ //Ensure that future tests are in the default state
Testing.ClassUnderTest.MessageBoxDependency = oldDependency;
}
}