silverlight   发布时间:2022-05-04  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了使用Moq让单元测试变得更简单大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

前几天调查完了unity。现在给我的任务是让我调查Moq。 以下是自己找了资料,总结并实践的内容。如果有表述和理解错误的地方。恳请指正。 什么是Moq?   Moq(英语发音是@R_944_10300@-you 或者只是@R_944_10300@)是一个针对.Net开发的模拟库,它从开始就完全充分利用了.NET3.5(LINQ表达式树)和C#3.0的新特性(lambda表达式)。它的目标是让模拟以一种自然的方式与现有单元测试进行集成

前几天调查完了unity。现在给我的任务是让我调查Moq。

以下是自己找了资料,总结并实践的内容。如果有表述和理解错误的地方。恳请指正。

什么是Moq?

 

@H_676_20@moq(英语发音是@R_944_10300@-you 或者只是@R_944_10300@)是一个针对.Net开发的模拟库,它从开始就完全充分利用了.NET3.5(LINQ表达式树)和C#3.0的新特性(lambda表达式)。它的目标是让模拟以一种自然的方式与现有单元测试进行集成,使它更加简单、直观,以避免开发人员被迫重写测试或高成本的学习测试框架。这使它成为了一个高生产力、类型安全、重构友好的模拟库。

从哪得到Moq?

 

如果你看过我的其他文章,我们可以直接使用 VS中的插件Nuget来@L_13_6@moq并且引用到指定的项目。

使用Moq让单元测试变得更简单

否则,我们可以从http://code.google.com/p/moq/这里得到Moq的最新版本。

可以模拟什么?局限性

 

首先,模拟的类不能是密封的。

其次,你不能直接模拟静态方法。因为Moq只能创建模拟对象实例。在这种情况下,间接的解决方案是我们可以在要模拟对象外包装一层,并且去模拟这个新对象。这种模式被称为适配器模式。

通常我们测试一个方法,它有可能调用好几个service。但是每次都去访问这些service的代价是很高的。我们可以通过模拟的方法让它模拟访问service,并且根据不同请求模拟返回响应的结果。

@H_61_3@moq原理

 

@H_676_20@moq是如何办到的?它只需要一个接口类型就可以生产一个对象?没错,就是这样。Moq使用 Castle DynamicProxy 完成这个任务。基本原理就是它利用反射机制的 Emit 功能动态生成一个空类型(也就是所有接口的方法都实例化,但是没有任何功能,只是一个程序骨架)。所以@R_944_10300@的能力就在于可以利用DynamicProxy的机制快速生产出一个假对象来,用于模仿真对象的行为。

 

@H_61_3@moq中的重要成员

 

@R_944_10300@

通过这个类,我们可以得到一个@R_944_10300@<T>对象。T可以是接口,也可以是类。它有一个public 和virtual属性。让我们看看下边的例子:

@H_450_72@
        //definE interface to be @R_944_10300@ed

        public interface IFake
        {

            bool DoSomething(String actionName);

        }

        //define the test method

        [TestMethod]

        public void test_Interface_IFake()
        {

            //@H_502_78@make a @R_944_10300@ Object by Moq

            var mo = new @R_944_10300@<IFake>();

            //Setup our @R_944_10300@ object

            mo.Setup(foo => foo.DoSomething("Ping"))

            .Returns(true);

            //Assert it!

            Assert.AreEqual(true,mo.object.DoSomething("Ping"));
        }
@H_450_72@
@H_450_72@

在上边的代码,我们通过传递泛型参数IFake去创建@R_944_10300@<IFake>的实例 模拟接口IFake。

接下来我们要调用Setup()方法去创建我们的模拟对象。注意,Setup方法的参数是一个lambda表达式。我们可以这样理解:当被模拟的对象foo调用它自己的方法DoSomething(),并且参数是Ping。添加后缀 return (true)我们可以理解为:前边的请求返回结果为真。这是我们指定的返回值。当一个请求调用DoSomething()方法时。如果传入的参数是Ping,那么我们会返回true。接下来,我们添加一个断言,去判断是否能得到预期结果。

注:Foo仅仅是一个词用作通用替代真实的东西,特别是在讨论技术想法和问题.

It

 

这是一个静态类,定义了静态的泛型方法:Is<TValue>, IsAny<TValue>, IsInRange<TValue>,和IsRegex。去过滤参数。看看下边例子:

@H_450_72@
public interface IEmailSender
        {

            bool Send(String subject,String body,String email);

        }
  [TestMethod]

        public void user_Can_Send_password()
        {

            var email@R_944_10300@ = new @R_944_10300@<IEmailSender>();

            email@R_944_10300@

            .Setup(sender => sender.Send(It.IsAny<String>(),It.IsAny<String>(),It.IsAny<String>()))

            .Returns(true);

        }
@H_450_72@ 复制代码
@H_450_72@ @L_262_47@

任何时候调用Send()方法,只要传入的参数是任何的String,我们定义他会返回true。

我们也可以根据lambda的优势订制一个规则:

          

@H_450_72@
  var productRepository = new @R_944_10300@<IProductRepository>();

            productRepository

            .Expect(p => p.Get(It.Is<int>(id => id > 0 && id < 6)))

            .Returns(newProduct.object);
@H_450_72@
@H_450_72@

这样我们可以设置这个id在0和6之间的时候才会返回一个新的对象。上边提及到的其他方法我们可以参这里的教程 Moq’s QuickStart

此外,这个类的增强版是 Match<T>,你完全可自定义模拟规则。

@R_944_10300@Behavior

 

这个类用于模拟对象的行为。就像是否按照认的模式去模拟。让我们进一步看看他的定义:

@H_450_72@
namespace Moq
{
    // SumMary:
    //     Options to customize the behavior of the @R_944_10300@.
    public enum @R_944_10300@Behavior
    {
        // SumMary:
        //     Causes the @R_944_10300@ to always throw an exception for invocations that don't have
        //     a corresponding setup.
        Strict = 0,//
        // SumMary:
        //     Will never throw exceptions,returning default values when necessary (null
        //     for reference types,zero for value types or empty enumerables and arrays).
        Loose = 1,//
        // SumMary:
        //     Default @R_944_10300@ behavior,which equals Moq.@R_944_10300@Behavior.Loose.
        Default = 1,}
}

现在,看看如下例子:

 

var @R_944_10300@ = new @R_944_10300@<IFake>(@R_944_10300@Behavior.Strict);

指定了@R_944_10300@行为是精准的,如果没有按照预期的Setup就会抛出异常。

@R_944_10300@Factory

 

这是一个模拟对象的工厂,我们不仅仅可以定制创建模拟对象的配置,也可以成批测试它们。看看下边例子:

 

var factory = new @R_944_10300@Factory(@R_944_10300@Behavior.Strict) { DefaultValue = DefaultValue.@R_944_10300@ };

            // Create a @R_944_10300@ using the factory setTings

            var foo@R_944_10300@ = factory.Create<IFake>();

            // Create a @R_944_10300@ overriding the factory setTings

            var bar@R_944_10300@ = factory.Create<IEmailSender>(@R_944_10300@Behavior.LoosE);

            // Verify all verifiable expectations on all @R_944_10300@s created through the factory

            factory.Verify();
@H_450_72@
@H_450_72@

在前边,我们已经介绍了传统方式的创建模拟对象,它不会去真正的调用方法,而是仅仅去执行一些假设:如果...那么返回... 。

在下边的例子里,我将继续介绍一些@R_944_10300@<T> 类中基本并且重要的方法

Verification

 

有时候,我们要确定一个方法是否被调用了,或者甚至要知道它被调用了多少次。一个比较传统的方式是使用Verify()方法。看看下边例子:

@R_944_10300@.Verify(foo => foo.DoSomething("Ping"),Times.Once());

上边的代码尝试验证DoSomething("Ping")需要被调用,并且只调用一次。出了Once选项,这里也有更多的选项可供你选择去决定这个方法需要被调用多少次。如: Atleast, AtleastOnce, AtMost, AtMostOnce, between, Equals, Exactly, Never,和Once

一旦我们已经模拟了对象,验证将是个轻松的任务,看看下边的例子:

@H_450_72@
   [TestMethod]

        public void test_FindByName_GetCalled()
        {

            // create some @R_944_10300@ data

            IList<Product> products = new List<Product>

{

            new Product { ProductId = 1,Name = "C# Unleashed",Description = "Short description here",Price = 49.99 },new Product { ProductId = 2,Name = "ASP.Net Unleashed",Price = 59.99 },new Product { ProductId = 3,Name = "Silverlight Unleashed",Price = 29.99 }

};

            @R_944_10300@<IProductRepository> @R_944_10300@ = new @R_944_10300@<IProductRepository>();

                //@R_944_10300@

                //.Setup(sender => sender.FindById(It.IsAny<int>()))

                //.Returns((int s) => products.Where(

                //    x => x.ProductId == s).Single());

            @R_944_10300@.object.FindById(1);

            @R_944_10300@

            .Verify(x => x.FindById(1),Times.Once());

        }
    }

在上边的例子里,有两个地方值得注意。

首先是@R_944_10300@.object.FindById(1)。为了在这个case里让一切变得简单,我们直接调用@R_944_10300@.object的方法。为什么呢?因为我们这个case只关注这个方法调用次数,而不关注返回值。当然,在实际的应用中我们很少这样做。

第二,你有没有注意到被注释掉的句子。它仅仅是一个“如果,那么”句子。意思是说,如果Setup 好了,就返回我们定义的值。

由于调查的时间有限,还有很多关于@R_944_10300@给力的地方我没有涉及到。我们可以去查看官方的资料。欢迎共同讨论。

 

 

资料

http://stephenwalther.com/blog/archive/2008/06/12/tdd-introduction-to-moq.aspx

http://code.google.com/p/moq/wiki/QuickStart
http://codeclimber.net.nz/archive/2009/10/23/10-resources-to-learn-moq.aspx
http://blogs.clariusconsulting.net/kzu/tag/moq/

http://blog.miniasp.com/post/2010/09/16/ASPNET-MVC-Unit-Testing-Part-03-Using-Mock-moq.aspx
http://dotnetslackers.com/articles/aspnet/Built-in-Unit-Test-for-ASP-NET-MVC-3-in-Visual-Studio-2010-Part-2.aspx#s4-using-moq-framework

大佬总结

以上是大佬教程为你收集整理的使用Moq让单元测试变得更简单全部内容,希望文章能够帮你解决使用Moq让单元测试变得更简单所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:moq使用单元变得测试简单
猜你在找的silverlight相关文章
其他相关热搜词更多
phpJavaPython程序员load如何string使用参数jquery开发安装listlinuxiosandroid工具javascriptcap