• .net单元测试——解除依赖


         最近在看.net单元测试艺术,我也喜欢单元测试,这里写一下如何在测试中解除对象间的依赖。

         假如有这样的一个需求,当用户登陆时,我需要对用户名和密码进行验证,然后再将用户名写入日志中。

      public class MyLogin
        {
            public bool Valid(string userName, string passWord)
            {
                var isValid = userName == "admin" && passWord == "123456";
    
                WriteLog(userName);
    
                return isValid;
    
            }
    
            private void WriteLog(string message)
            {
                //....写入数据库或文件中
            }
    }

          上面代码中,如果我们写单元测试时会发现,WriteLog方法依赖于文件或数据库时,这时测试会比较困难一些。首先我们需要对解除依赖,再进行测试。代码如下:

    public class MyLogin
        {
            public ILog Log { get; set; }
    
            public bool Valid(string userName, string passWord)
            {
                var isValid = userName == "admin" && passWord == "123456";
    
                Log.Write(userName);
    
                return isValid;
            }
        }
    
        public interface ILog
        {
            void Write(string message);
        }

      这时我们引入了ILog接口,在调用Valid方法前,需要对属于Log进行赋值,这里,我们便解除了对象之间的依赖。我们开始写单元测试,测试中,我们需要自己模拟一个桩对象。

        桩对象是对系统中现有依赖项的一个替代品,可人为控制,通过使用桩对象,无需涉及依赖项,即可直接对代码进行测试。

      测试框架这里我选用了NUnit框架。测试代码如下:

    [TestFixture]
        public class MyLoginTest
        {
            [Test]
            public void Vaild_Test()
            {
                MyLogin login = new MyLogin();
    
                login.Log = new TestLog();
     
                var isLogin = login.Valid("admin", "123456");
    
                Assert.AreEqual(isLogin, true);
            }
        }
        public class TestLog : ILog
        {
            public void Write(string message)
            {
                //nothing
            }
        }

      这里我定义了一个类TestLog,这个类所生成的对象就是一个桩对象,桩对象的目的是为了替换测试中的依赖项,有些时候,依赖项可能需要文件或某些配置,导致很难测试,所以,为了方便测试,我们使用了桩对象。

      上面的例子中,我们通过接口完成了对象间的依赖解除,再通过属性完成对接口的赋值,如果不使用属性,我们还可以用别的方法对接口进行赋值。

    1. 通过构造函数进行赋值。
    public MyLogin(ILog log)
      Log = log;

         在测试中,初始化Mylgoin对象时,把桩对象传给构造函数即可。

      2.  通过工厂模式进行赋值。

      通过工厂类来生成ILog对象,并且工厂类要允许传入ILog对象,代码如下:

    public class MyLogin
        {
            public bool Valid(string userName, string passWord)
            {
                var isValid = userName == "admin" && passWord == "123456";
    
                var log = Factory.CreateLog();
    
                log.Write(userName);
    
                return isValid;
            }
        }
    
        public interface ILog
        {
            void Write(string message);
        }
    
        public class Factory
        {
            private static ILog iLog;
    
            public static ILog CreateLog()
            {
                return iLog;
            }
    
            public static void SetLog(ILog log)
            {
                iLog = log;
            }
     }

      测试类中,要对Factory的SetLog方法进行赋值,其它操作基本不变。

      3.  使用虚方法或IOC容器。

      这些操作需要根据实际情况去使用。不要因为测试去改变你的设计(过度测试),除非你的设计无法测试。

      总结: 对于开发人员来讲,单元测试是很重要一项工作。它会让你的代码结构更加清晰,代码的可读性也会更好。下一节,写一下如何使用框架进行测试,毕竟写桩对象还是要花很多时间的。

  • 相关阅读:
    使用PHP获取用户客户端真实IP的解决方案
    PHP中使用mkdir创建多级目录的方法
    javascript中将字符串转换为json格式的三种方法
    Codeigniter处理用户登录验证后URL跳转
    PHP正则表达式匹配URL中的域名
    开源项目列表
    PG JDBC COPY感谢原作者
    if中return的用法
    读数据库查询的 ResultSet时java.sql.SQLException: 流已被关闭
    一篇讲JAVA JDBC的好文章
  • 原文地址:https://www.cnblogs.com/xingzhang/p/NetUnit1.html
Copyright © 2020-2023  润新知