[ASP. NET mvc3] Use Moq to simplify Unit Testing

Source: Internet
Author: User

A few days ago, unity was investigated. Now, I want to investigate Moq.

The following is a summary and practice of the materials. If there is a wrong expression or understanding. Please correct me.

What is Moq?

 

Moq (the English pronunciation is mock-you or just mock) is a target. net Development simulation library, which has been fully utilized from the very beginning. new Features of net3.5 (LINQ Expression Tree) and C #3.0 (lambda expression ). Its goal is to integrate the simulation with existing unit tests in a natural way, making it simpler and more intuitive, to avoid developers being forced to rewrite the test or high-cost learning test framework. This makes it a highly productive, secure, and refactored simulation library.

Where can I get Moq?

 

If you see my otherArticleYou can directly use the nuget plug-in vs to obtain Moq and reference it to the specified project.

Otherwise, we can get the latest moqversion from http://code.google.com/p/moq/here.

What can I simulate? Limitations

 

First, the simulated class cannot be sealed.

Second, you cannot directly simulate static methods. Because Moq can only create simulated object instances. In this case, the indirect solution is that we can simulate the new object by simulating an outer layer of the object. This mode is called the adapter mode.

We usually test a method, which may call several services. However, each time you access these services, the cost is very high. We can simulate the access to the service and simulate the response results based on different requests.

Moq Principle

 

How does Moq do it? It only needs one interface type to produce one object? That's right. Moq uses Castle dynamicproxy to complete this task. The basic principle is that it uses the reflection mechanism's emit function to dynamically generate an empty type (that is, all interface methods are instantiated, but there is no function, justProgramSkeleton ). Therefore, Mock's ability lies in the ability to use the dynamicproxy mechanism to quickly produce a false object for imitating the behavior of a real object.

 

Important member in Moq

 

Mock

Through this class, we can get a mock <t> object. T can be an interface or a class. It has a public and virtual attribute. Let's take a look at the following example:

         //  Define interface to be mocked  

Public Interface Ifake
{

Bool Dosomething (String Actionname );

}

// Define the test method

[Testmethod]

Public Void Test_interface_ifake ()
{

// Make a mock object by Moq

VaR Mo =New Mock <ifake> ();

// Setup our mock object

Mo. Setup (FOO => Foo. dosomething ( " Ping " ))

. Returns ( True );

// Assert it!

Assert. areequal (True , Mo. Object. dosomething ( " Ping " ));
}

InCodeYou can pass the generic parameter ifake to create the ifake instance simulation interface of mock <ifake>.

Next, we will call setup () to create a simulated object. Note that the parameter of the setup method is a Lambda expression. It can be understood as follows: when the simulated object Foo calls its own method dosomething () and the parameter is Ping. After the suffix return (true) is added, we can understand that the result returned by the request at the front side is true. This is the specified return value. When a request calls the dosomething () method. If the input parameter is Ping, true is returned. Next, we will add an assertion to determine whether expected results can be obtained.

Note: foo is just a word used as a general replacement for the real thing, especially when discussing technical ideas and problems.

It

 

This is a static class that defines static generic methods: is <tvalue>, isany <tvalue>, isinrange <tvalue>, and isregex. Filter parameters. Take a look at the following example:

  Public   interface  iemailsender 
{< br> bool send ( string subject, string body, string email );

}< br> [testmethod]
Public void user_can_send_password ()
{< br> var emailmock = New mock ();
emailmock
. setup (sender => sender. send (it. isany string (), it. isany string (), it. isany string ()
. returns ( true );

}

Call the send () method at any time. If the input parameter is any string, we define that it will return true.

We can also customize a rule based on Lambda's advantages:

 
VaRProductrepository =NewMock <iproductrepository> ();

Productrepository

. Reverse CT (P => P. Get (it. is <Int> (ID => ID>0& Id <6)))

. Returns (newproduct. Object );

 

In this way, a new object is returned only when the ID is between 0 and 6. For other methods mentioned above, refer to the Moq's Quickstart tutorial here.

In addition, the enhanced version of this class is match <t>. You can customize simulation rules.

Mockbehavior

 

This class is used to simulate object behavior. It is like whether to simulate it in the default mode. Let's take a further look at his definition:

 Namespace Moq
{
// Summary:
// Options to customize the behavior of the mock.
Public Enum Mockbehavior
{
// Summary:
// Causes the mock 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 mock behavior, which equals Moq. mockbehavior. Loose.
Default = 1 ,
}
}

 

Now, let's take a look at the following example:

 

 
VaRMock =NewMock <ifake> (mockbehavior. Strict );

The specified mock action is accurate. If the setup fails as expected, an exception is thrown.

Mockfactory

 

This is a factory for simulation objects. We can not only customize the configurations for creating simulation objects, but also test them in batches. Take a look at the following example:

 

  var  factory =  New  mockfactory (mockbehavior. strict) {defaultvalue = defaultvalue. mock };< br> ///   Create a mock using the factory settings   

var foomock = factory. create ();
// Create a mock overriding the factory settings

var barmock = factory. create (mockbehavior. loose);
/// verify all verifiable expectations on all mocks created through the factory

factory. verify ();

In the front, we have introduced the traditional method of creating a simulated object. Instead of calling the method, we just execute some assumptions: If... then return ....

In the example below, I will continue to introduce some basic and important methods in the mock <t> class.

Verification

 

Sometimes we need to determine whether a method has been called or even how many times it has been called. A more traditional method is to use the verify () method. Take a look at the following example:

 
Mock. Verify (FOO => Foo. dosomething ("Ping"), Times. Once ());

The above code tries to verify that dosomething ("ping") needs to be called only once. With the once option, more options are available for you to choose how many times the method needs to be called. Such as atleast, atleastonce, atmost, atmostonce, between, equals, exactly, never, and once

Once we have simulated the object, verification will be a simple task. Let's take a look at the following example:

[Testmethod]

Public Void Test_findbyname_getcalled ()
{

// Create some mock 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 " ,

Description = " Short description here " , Price = 59.99 },

New Product {productid = 3 , Name = " Silverlight unleashed " ,

Description = " Short description here " , Price = 29.99 }

};

Mock <iproductrepository> mock = New Mock <iproductrepository> ();

// Mock

// . Setup (sender => sender. findbyid (it. isany <int> ()))

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

// X => X. productid = s). Single ());

Mock. Object. findbyid ( 1 );

Mock

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

}
}

In the above example, there are two points worth noting.

First, mock. Object. findbyid (1 ). To make everything simple in this case, we call the mock. Object method directly. Why? This case only focuses on the number of calls to this method, rather than the return value. Of course, we seldom do this in practical applications.

Second, have you noticed the sentence that has been commented out. It is just a "if, then" sentence. It means that if setup is complete, the defined value will be returned.

Due to the limited time spent in the investigation, there are still a lot of things I haven't covered about mock. We can view official materials. Welcome to the discussion.

 

 

References

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

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.