• .net 单元测试


    都说测试驱动开发,但是想写好单元测试其实不容易,不是因为测试用例难以构造,而是因为很多时候方法非常复杂

    其中部分测试想要完成就十分费力,其中让人崩溃的地方主要如下:

    • 实例私有函数
    • 实例静态私有函数
    • 十分难以构造的对象

    实例私有函数

    继承重写

    可以通过反射来进行测试,但是想想你写的代码才200行,测试的代码1000行,就让你很崩溃
    之前我主要是把这个方法写成protected 然后通过在测试代码中写子类来进行测试。
    但是事实上这已经破坏了封装,而且很多时候,为了能够写出测试,不得不改变API的设计,将一些私有实例变量都扔到了参数里面,方便自己写测试。

    
    // 原来的类
    
    public class A{
        private SomeType someType;
    
        private SomeType someMethod();
    
    }
    
    // 通过改变原来的类的限制,将其改为protected
    
    public class A {
        protected SomeType someType;
    
        protected SomeType someMethod();
    
    }
    
    // 尤其是当测试的函数可能只是改变对象状态的void方法的时候,为了验证对象状态的改变,就必须使用protected限制符
    // 通过这种方法进行测试其实比较麻烦,而且还破坏了原来的设计
    class TestClass : A {
        public SomeType testSomeMethod() {
            return base.someMethod();
        }
    }
    
    

    不过,当用来测试部分的本来就是用来继承的类的时候,这个方法还算可以

    当然还有一个很方便的方法,就是使用PrivateObject

    PrivateObject

    // 比如这个类内部的私有方法
    
    public class Calculate
    
        private int Add(int a, int b)
        {
            return a + b;
        }
    }
    
    // 可以通过微软UT框架自带的PrivateObject来完成,没看源码,不过看到Invoke,估计也是使用反射写的
    
    [TestMethod]
    public void TestPrivateAdd()
    {
        PrivateObject po = new PrivateObject(new Calculate());
    
        Assert.AreEqual(po.Invoke("Add", 1, 2), 3);
    }
    

    私有静态方法

    当然了,碰到实例方法可以使用继承测试,但是碰到了静态方法,本人立刻就没有办法了,所以Google了一下
    发现了微软的PrivateType对象

    PrivateType

    比较类似于PrivateObject

    public class Calculate
    {
        internal static int AddStatic(int a, int b)
        {
            return a + b;
        }
    }
    
    // 可以通过PrivateType的 InvokeStatic来调用静态方法
    [TestMethod]
    public void TestInternalStaticAdd()
    {
        PrivateType po = new PrivateType(typeof(Calculate));
    
        Assert.AreEqual(po.InvokeStatic("AddStatic", 1, 2), 3);
    }

    难以构造的对象

    最简单的例子,你测试一个网络请求的时候,构造一个request就让人吐血
    当做一个复杂系统的时候,哪怕你只调用一个复杂结构的部分对象,但是因为对象的复杂,你可能就需要阅读超多的API

    所以就有了Mock框架,本文使用的Mock框架是Moq的mock对象,用起来还算简单

    感觉很有元编程的感觉

    // 之前测试的时候因为读取数据库的对象是一个IDataReader
    // 看到这个接口我完全不知道怎么构造,该使用哪一个子类来构造,但是有了Mock就不同了
    
    [TestMethod()]
    public void FillRuleTest()
    {
        // 通过mock来构造复杂对象,其中IDataReader是我需要构造的对象
        Mock<IDataReader> mock = new Mock<IDataReader>();
        mock.Setup(m => m["abc"]).Returns("abc");
    
        // 构造完成后,可以通过mock.Object来获取对应构造的对象
        IDataReader mockObj = mock.Object;
        Assert.AreEqual(mockObj["abc"].ToString(), "abc");
    
        // 现在构造参数就会容易很多,你写的Returns也能返回你想要的值
    }
  • 相关阅读:
    Linux c 开发-17 pugixml xml_node Collection和一个数组的值比较示例
    Linux c 开发-16 不需要头文件也可以编译???
    SourceInsight快捷键
    Linux c 开发-16 VsCode下使用CMakeFile编译项目
    java 字符串转Base64
    Linux c 开发-15 Ubuntu子系统中使用串口
    Linux c 开发-14 一例不能直接调试gdb程序的解决办法
    Ubuntu子系统与Windows互相访文件系统
    Linux c 开发-13 Makefile与VisualStudio Linux C环境对应关系
    Linux c 开发-12 创建子进程
  • 原文地址:https://www.cnblogs.com/qitian1/p/6461577.html
Copyright © 2020-2023  润新知