使用Visual Studio进行单元测试-Part4
2015-10-31 19:48
316 查看
本文主要介绍Visual Studio(2012+)单元测试框架的一些技巧:
如何模拟类的构造函数
优化代码,便于测试
被测试的类:该类根据传入的参数不同而调用不同的子类进行操作。
当输入(shapeType)为T的时候实例化Triangle类。
当输入为非T的时候实例化Rectangle类。
上面的测试主要是为了测试这个if的调度是否正确,而不关心Calculate到底做了什么。所以上面测试的验证不应该通过CalculateArea的值来进行验证,因为这违反了单元测试的“单元”二字。
因为App.Calculate("T");所以Triangle类被实例化(triangleConstructed为true),而Rectangle类没有被实例化(rectangleCOnstructed为false)。
相反,得下面的测试结果:
上面使用一个简单工场先构建一个IShape对象,这样这个构建过程以方法的形式公布出来,可以就这个CreateShape方法进行单独测试。
简单调整了一下代码,测试代码就变的非常简单,且非常清晰,当然针对优化后的代码之前使用Shim方式的测试代码还是可以继续运行的。
如何模拟类的构造函数
优化代码,便于测试
一、如何模拟类的构造函数
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。而是应该在测试的过程中慢慢调整代码,让代码变的可“测试”。相关文章推荐
- 从Oracle中数据库中读取以Blob类型存储的图片显示在jsp页面中
- 基于java的Socket简单知识做的多人聊天室
- Codeforces Round #273 (Div. 2)D. Red-Green Towers DP
- Android中布局优化
- Large Scale Machine Learning--An Engineering Perspective--目录
- android studio入门
- 新建一个Activity通过按钮打开它,再通过按钮关闭它
- 中国大学MOOC-陈越、何钦铭-数据结构 统计工龄
- 英语学习不能断
- C++实现图的十字链表表示及相关各算法
- 代理者模式----设计模式系列
- iOS系统开发:打电话、发短信
- 电压电流到底是什么?
- ubuntu学习小结(2)
- 碰撞检测
- jquery 获取及设置input各种类型的值
- ThreadLocal讲解
- property declaration 属性声明
- 显式Intent与隐式Intent
- 近三月杂谈