码迷,mamicode.com
首页 > 其他好文 > 详细

Unit Test Via Visual Studio-Part4

时间:2015-10-31 21:17:44      阅读:237      评论:0      收藏:0      [点我收藏+]

标签:

本文主要介绍Visual Studio(2012+)单元测试框架的一些技巧:

  1. 如何模拟类的构造函数
  2. 优化代码,便于测试

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

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可以分成两个

  1. 当输入(shapeType)为T的时候实例化Triangle类。
  2. 当输入为非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。而是应该在测试的过程中慢慢调整代码,让代码变的可“测试”。

Unit Test Via Visual Studio-Part4

标签:

原文地址:http://www.cnblogs.com/kmpp/p/Shim_Constructor_And_Make_Code_Testable.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!