首页 > 学院 > 开发设计 > 正文

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

2019-11-15 02:28:32
字体:
来源:转载
供稿:网友

.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容器。

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

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


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表