您的位置:首页 > 其它

使用Visual Studio进行单元测试-Part4

2015-10-31 19:48 316 查看
本文主要介绍Visual Studio(2012+)单元测试框架的一些技巧:

如何模拟类的构造函数

优化代码,便于测试

一、如何模拟类的构造函数

1.1 被测代码

基础代码,IShape分别有Rectangle和Triangle俩个子类。有一个简单的CalculateArea方法。

namespace BlogDemo.UTDemo
{
public interface IShape
{
int CalculateArea();
}

class Rectangle : IShape
{
public int CalculateArea()
{
return 1;
}
}

class Triangle : IShape
{
public int CalculateArea()
{
return 100;
}
}
}


被测试的类:该类根据传入的参数不同而调用不同的子类进行操作。

class App
{
public void Calculate(string shapeType)
{
if (shapeType == "T")
{
new Triangle().CalculateArea();
}
else
{
new Rectangle().CalculateArea();
}
}
}


1.2 测试目标

现在要测试App类的Calculatef方法,测试该类的case可以分成两个

当输入(shapeType)为T的时候实例化Triangle类。

当输入为非T的时候实例化Rectangle类。

上面的测试主要是为了测试这个if的调度是否正确,而不关心Calculate到底做了什么。所以上面测试的验证不应该通过CalculateArea的值来进行验证,因为这违反了单元测试的“单元”二字。

1.3 测试代码

在ms.test框架下,可以通过ShimClassName.Constuctor来模拟类名为ClassName的类的构造函数

[TestClass]
public class AppTests
{
[TestMethod]
public void CalculateTest()
{
using (ShimsContext.Create())
{
var triangleConstructed = false;
ShimTriangle.Constructor = (@this) =>//此处模拟Triangle类的构造函数,如果Triangle被实例化,则triangleConstructed为true
{
triangleConstructed = true;
};

var rectangleConstructed = false;
ShimRectangle.Constructor = (@this) =>//此处模拟Rectangle类的构造函数,如果Rectangle被实例化,则rectangleConstructed为true
{
rectangleConstructed = true;
};

App.Calculate("T");
Assert.IsFalse(rectangleConstructed);
Assert.IsTrue(triangleConstructed);
}
}
}


因为App.Calculate("T");所以Triangle类被实例化(triangleConstructed为true),而Rectangle类没有被实例化(rectangleCOnstructed为false)。

相反,得下面的测试结果:

[TestClass]
public class AppTests
{
[TestMethod]
public void CalculateTest()
{
using (ShimsContext.Create())
{
var triangleConstructed = false;
ShimTriangle.Constructor = (@this) =>//此处模拟Triangle类的构造函数,如果Triangle被实例化,则triangleConstructed为true
{
triangleConstructed = true;
};

var rectangleConstructed = false;
ShimRectangle.Constructor = (@this) =>//此处模拟Rectangle类的构造函数,如果Rectangle被实例化,则rectangleConstructed为true
{
rectangleConstructed = true;
};

App.Calculate("F");//非T。Rectangle将会被实例化
Assert.IsTrue(rectangleConstructed);
Assert.IsFalse(triangleConstructed);
}
}
}


二、代码优化。

在TTD中有一种说法叫做代码不可测试,其实要不是ms.test框架的Shim功能强大,上面的代码其实是不可测试的。上面的代码完全可以进行优化。

2.1 优化后的代码

public class App
{
public static void Calculate(string shapeType)
{
var shape = CreateShape(shapeType);
shape.CalculateArea();
}

public static IShape CreateShape(string shapeType)
{
if (shapeType == "T")
{
return new Triangle();
}
else
{
return new Rectangle();
}
}
}


上面使用一个简单工场先构建一个IShape对象,这样这个构建过程以方法的形式公布出来,可以就这个CreateShape方法进行单独测试。

2.2 优化后的测试代码

[TestMethod]
public void CreateShape_TriangleConstructed_Test()
{
var shape = App.CreateShape("T");
Assert.AreEqual(shape.GetType(), typeof(Triangle));
}

[TestMethod]
public void CreateShape_RectangleConstructed_Test()
{
var shape = App.CreateShape("F");
Assert.AreEqual(shape.GetType(), typeof(Rectangle));
}


简单调整了一下代码,测试代码就变的非常简单,且非常清晰,当然针对优化后的代码之前使用Shim方式的测试代码还是可以继续运行的。

三、结论

使用微软的测试框架很多之前“不能测试”的代码依然可以继续测试,但是这不是好习惯,测试不应该过于依赖测试框架的feature。而是应该在测试的过程中慢慢调整代码,让代码变的可“测试”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: