• Moq MVC 初窥门径(一)


    一. 预备知识

            单元测试:单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证

            Mock测试:在测试过程中,对于某些不容易构造或者 不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法

            Lambda表达式

            Linq(Language INtegrated Query)

    二. 初识Moq

            Moq(读作“Mock-you”或“Mock”)是.net平台下最有生产力,类型安全和重构友好的mocking库。

            在进行单元测试的时候,经常会碰到这些情景:

            1.想要对业务逻辑层的某个AService方法进行单元测试,而该方法内部却调用了数据链路层的ADataAccess方法,这时候的单元测试,其实已经破坏了单元测试功能点单一的原则,因为AService方法的单元测试首先需要ADataAccesss正常运行。更有甚者,这时候测试环境根本无法连接数据库。

            2.想要对MVC的 Controller层的某AProcess方法进行单元测试,但是该方法内部调用了HttpContext的相关属性或方法。若要进行单元测试,光是模拟Web环境就要花费大量时间。

            而Moq就我们提供了模拟真实对象行为的能力,然后交给被测试功能使用,以此判断被测试功能是否正确。

           注意:Moq只能模拟接口或抽象类。

    三. Simple Demo

    public interface ITalk

    {//简单接口

    string Talk();

    }

    public abstract class Person

    {//简单抽象类

    public abstract bool IsTalk();

    }

    class Program

    {

    static void Main(string[] args)

    {

    //简单的模拟接口

    var iTalk = new Mock<ITalk>();

    iTalk.Setup(i => i.Talk()).Returns("Hello,I'm Mock");

    Console.WriteLine(iTalk.Object.Talk());

    //若该行代码放到iTalk.Object.Talk(),则会引发异常,因为Talk()没有被调用过

    iTalk.Verify(i => i.Talk(), Times.AtLeastOnce());

    //简单的模拟抽象类

    var aPerson = new Mock<Person>();

    aPerson.Setup(a=>a.IsTalk()).Returns(false);

    Console.WriteLine(aPerson.Object.IsTalk());

    Console.ReadLine();

    }

    }

                 F5运行后,效果如下

                image

                 上边的例子可以看到,完全没有实现过的接口或者抽象类,可以通过Moq模拟一个虚拟的对象

    四. Moq的用法

            Moq中最常用的类分别是

            1.Mock<T> 提供一个模拟实现了T接口(或抽象类)的对象

     

    名称

    描述

    常用方法

    Setup (Expression<Action<T>>)

    核心方法,通过Lambda设置模拟对象的方法

    Verify(Expression<Action<T>> )

    核心方法,验证模拟对象方法是否(按照规定的传入参数)执行并通过。该方法有多个重载,分别验证方法执行的次数,失败时的错误消息提示

    属性

    Object

    模拟对象的实例

           2.It 为了使Moq模拟的方法根据不同的传入参数而有不同的行为,Moq提供了该类,可以指定一个传入参数的匹配条件。

     

    名称

    描述

    IsAny< TValue>

    匹配给定TValue类型的任何值

    IsInRange<TValue>

    匹配指定范围的任何值

    IsRegex(String)

    匹配符合给定正则表达式模式的字符串

    五. Moq实战

            回到刚最开始时提到的情景1.

            即数据库访问层没有实现,如何测试业务逻辑层的某个方法是否正确。

            模拟代码如下:

    文件1. DataModel

    public class DataModel

    {

    public string Id { get; set; }

    }

    文件2.IDataAccess

    public interface IDataAccess

    {

    List<DataModel> GetDataModel();

    }

    文件3IDataModelService

    public interface IDataModelService

    {

    int GetCount();

    }

    文件4DataAccess

    public class DataAccess : IDataAccess

    {

    public List<DataModel> GetDataModel()

    {

    return null;

    }

    }

    文件5DataModelService

    public class DataModelService : IDataModelService

    {

    private IDataAccess iDataAccess;

    public DataModelService()

    {

    iDataAccess = new DataAccess();

    }

    public DataModelService(IDataAccess iData)

    {

    iDataAccess = iData;

    }

    public int GetCount()

    {

    return iDataAccess.GetDataModel().Count;

    }

    }

    测试文件 public class Test

    {

    static void Main(string[] args)

    {

    //模拟数据

    List<DataModel> lisData = new List<DataModel>() { new DataModel { Id = "1" }, new DataModel { Id = "2" } };

    //模拟对象

    var data = new Mock<IDataAccess>();

    data.Setup(d => d.GetDataModel()).Returns(lisData);

    //测试方法

    DataModelService dataService = new DataModelService(data.Object);

    Console.WriteLine(dataService.GetCount());

    Console.ReadLine();

    }

    }

               运行结果截图:

                image

               情景2:

                有时间做补

    六.资料

    Moq下载:http://code.google.com/p/moq/ 内含帮助文档

    Moq入门:http://www.codethinked.com/post/2009/03/08/Beginning-Mocking-With-Moq-3-Part-1.aspx

    http://www.codethinked.com/post/2009/03/10/Beginning-Mocking-With-Moq-3-Part-2.aspx

    http://www.codethinked.com/post/2009/03/10/Beginning-Mocking-With-Moq-3-Part-3.aspx

    http://www.codethinked.com/post/2009/03/10/Beginning-Mocking-With-Moq-3-Part-4.aspx

  • 相关阅读:
    POJ 3660 Cow Contest 任意两点之间的关系 Floyd
    CDOJ 1146 A
    TTTTTTTTTTTTTT CDOJ Sliding Window 线段树(nlogn)或双端队列(n) 模板
    CDOJ 203 并查集+优先队列 好题
    CDOJ 1073 线段树 单点更新+区间查询 水题
    CDOJ 1070 秋实大哥打游戏 带权并查集
    CDOJ 1063 堆排序模板
    CDOJ 1069 秋实大哥去打工 单调栈 下标处理
    CDOJ 1061 C
    巨蟒python全栈开发django14:Form组件
  • 原文地址:https://www.cnblogs.com/qiuyeyaozhuai/p/2913983.html
Copyright © 2020-2023  润新知