标签:
本文主要介绍Visual Studio(2012+)单元测试框架的一些技巧:
基础代码,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();
}
}
}
现在要测试App类的Calculatef方法,测试该类的case可以分成两个
上面的测试主要是为了测试这个if的调度是否正确,而不关心Calculate到底做了什么。所以上面测试的验证不应该通过CalculateArea的值来进行验证,因为这违反了单元测试的“单元”二字。
在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功能强大,上面的代码其实是不可测试的。上面的代码完全可以进行优化。
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方法进行单独测试。
[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。而是应该在测试的过程中慢慢调整代码,让代码变的可“测试”。
Unit Test Via Visual Studio-Part4
标签:
原文地址:http://www.cnblogs.com/kmpp/p/Shim_Constructor_And_Make_Code_Testable.html