我目前正在编写一些方法,对表单控件执行一些基本操作,例如Textbox,Groupbox,这些操作是通用的,可以在任何应用程序中使用。
我开始编写一些单元测试,只是想知道我应该使用System.Windows.Forms中的实际表单控件,还是应该模拟我试图测试的部分。例如:
假设我有这个控制方法,如果它是一个文本框,它将清除文本属性,如下所示:
public static void clearall(this Control control)
{
if (control.GetType() == typeof(TextBox))
{
((TextBox)control).Clear();
}
}
然后我想测试这个方法,所以我做了这样的事情:
[TestMethod]
public void TestClear()
{
List<Control> listofcontrols = new List<Control>();
TextBox textbox1 = new TextBox() {Text = "Hello World" };
TextBox textbox2 = new TextBox() { Text = "Hello World" };
TextBox textbox3 = new TextBox() { Text = "Hello World" };
TextBox textbox4 = new TextBox() { Text = "Hello World" };
listofcontrols.Add(textbox1);
listofcontrols.Add(textbox2);
listofcontrols.Add(textbox3);
listofcontrols.Add(textbox4);
foreach (Control control in listofcontrols)
{
control.clearall();
Assert.AreEqual("", control.Text);
}
}
我应该将System.Window.Forms的referance添加到我的单元测试并使用真正的Textbox对象吗?或者我做错了吗?
注意:上面的代码只是一个例子,我没有编译或运行它。
答案 0 :(得分:6)
如果您尝试通过模拟与UI控件的交互来对应用程序逻辑进行单元测试,则应使用MVC pattern进行一些抽象。然后你可以只有一个存根视图并从单元测试中调用控制器方法。
如果它是您尝试进行单元测试的实际控制,那么你就拥有了我。
答案 1 :(得分:5)
有几种模式可用于将UI表示与UI逻辑分离,包括模型 - 视图 - 控制器和模型 - 视图 - 演示者(AKA Humble Dialog)的各种化身。 Humble Dialog专门用于简化单元测试。你绝对应该在你的设计库中拥有这些UI模式之一。
但我发现,对于简单的表单,当框架支持它时,直接针对真实的UI控件进行测试非常简单。我已经在Java Swing和Windows.Forms中构建了完全测试优先的非常强大的UI。我无法在SWT或ASP.NET中管理它并恢复到MVP。
用于测试这样的事情......
[Test] public void ShouldCopyFromAvailableToSelectedWhenAddButtonIsCLicked(){
myForm.AvailableList.Items.Add("red");
myForm.AvailableList.Items.Add("yellow");
myForm.AvailableList.Items.Add("blue");
myForm.AvailableList.SelectedIndex = 1;
myForm.AddButton.Click();
Assert.That(myForm.AvaiableList.Items.Count, Is.EqualTo(2));
Assert.That(myForm.SelectedList.Items[0], Is.EqualTo("yellow"));
}
...直接针对UI控件工作正常。但是如果你想开始测试鼠标移动,击键或拖放,你最好选择一个比Brian建议的更强大的UI模式。
答案 2 :(得分:3)
如果您的代码依赖于System.Windows.Forms.Control,您建议的内容甚至不会编译。您的Control和Textbox版本只是错误的类型。
相反,如果您将UI和Logic与接口分开,那么您可以这样做......就像这样:
public interface ITextBox
{
public string Text {get; set;}
}
public class TextBoxAdapter : ITextBox
{
private readonly System.Windows.Forms.TextBox _textBox;
public TextBoxAdapter(System.Windows.Forms.TextBox textBox)
{
_textBox = textBox;
}
public string Text
{
get { return _textBox.Text; }
set { _textBox.Text = value; }
}
}
public class YourClass
{
private ITextBox _textBox;
public YourClass(ITextBox textBox)
{
_textBox = textBox;
}
public void DoSomething()
{
_textBox.Text = "twiddleMe";
}
}
然后,在您的测试中,您需要做的就是创建一个模拟,伪造或存根ITextBox并将其传入。
当我做这样的事情时,我会创建一个稍微高一点的界面......我创建一个看起来很像整个UI的界面,并让UI实现界面。然后,我可以根据需要旋转UI,而不必真正知道它是一个Forms控件。
顺便说一句,如果您想采用创建实际控件的方法,请考虑此博客文章:http://www.houseofbilz.com/archive/2008/10/12/winforms-automation-extensions.aspx