I am writing a test case for my User Control which will prompt using MessageBox.Show for User Action asking to process or Cancel the operation. How can I design my unit test to mimic the User interaction to proceed?.
I do not want to refactor to move the logic to middle tier. This is a simple case of getting User Consent and proceeding with middle tier call. Any help/ideas restructuring UI for this scenario will also be helpful.
Clicking a button is nothing else than invoking the corresponding click
event. So you might want to build your test around that.
Even better (if this isn't the case yet), move your code out of the frontend, and build your unittests around the business actions, you'd otherwise invoke by clicking a button.
update after edit by author
You are not going to get this to work as long as you are not prepared to split things, you cannot build your unit tests around 'click here', 'click there'. Imagine the following code:
private int MyFunction()
{
bool insideVariable = false;
if(insideVariable)
return 1;
else
return 2;
}
You will never be able to unit test the case where insideVariable is set to true; You can either:
return 1
statement is somewhere in your middle tierreturn 1
statement is a method in your GUI. You can then test that function.Application frontends should be quite easily to replace, so no business logic should be stored in there. Unit tests are just another frontend living next to your main GUI.
Providing a solution would be much easier with the UI method or related methods posted. Also seeing the TestMethod(s) could help even incomplete methods.
If I understand your test purpose is to determine what happens on the different click possibilities?
You could set up your actual method that triggers the MessageBox
using Inversion of Control and Dependency Injection like this:
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
}
}
}
and then the test method (remember to include the using Microsoft.VisualStudio.TestTools.UnitTesting;
at the top) would be like this:
[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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With