测试中,自己如何创建mock对象
一个类 A,我要对它某方法(取名为x)的代码进行测试,在x中会创建 窗口 B,并且执行B中的y方法。
代码如下:
ClsA.cs
class ClsA
{
public void x()
{
FrmB oF = new FrmB();
oF.y();
int j = 0;
int k = 5 / j;
}
}
FrmB.cs
public partial class FrmB : Form
{
public FrmB()
{
InitializeComponent();
}
public void y()
{
MessageBox.Show("运行了很多复杂代码!");
}
}
测试代码ClsATest.cs
/// <summary>
/// x 的测试
/// </summary>
[TestMethod()]
public void xTest()
{
ClsA target = new ClsA();
target.x();
}
这个测试存在的问题:在ClsA.x()中,启动了 FrmB ,并且“运行了很多复杂代码!”。
[解决办法]
你管别人说什么“足够好”呢?你到底想用它干什么实际的事情呢?
------解决方案--------------------
只因为你是在重复造轮子。
[解决办法]
如果你注重测试的话,应该先写测试代码,再写实际程序,这样就会强迫你在写实际程序时为测试留好接口。
在ClsA中用new FrmB()这样的写法,就表示ClsA和FrmB是紧密联系在一起的。FrmB的改变可能会影响ClsA,如果想复用ClsA的话,ClsA也必须和FrmB一起作为一个整体被引用。而通过构造函数传递IfFrmB接口这种IoC/DI方式,则ClsA和FrmB没有直接联系。只要IfFrmB接口稳定,对FrmB的修改不影响ClsA。
[解决办法]
如果你测试的方法位于业务层,它本来就应该和界面是分离的。不应该在测试时用开关来跳过这些UI方法的调用,而是应该设计时就采用依赖注入的方式,把UI作为一个服务接口传到这个方法所在的类,测试时也很容易伪造一个ui的mock对象,提供一些假的输入,来测试这个方法的各种分支。
而UI本身的测试,通常是用ui automation工具,来模拟鼠标、键盘的操作,看界面的反应是否正常,这个和一般的代码测试是不同的。