本文转自:http://www.asp.net/mvc/tutorials/older-versions/unit-testing/creating-unit-tests-for-asp-net-mvc-applications-cs

The goal of this tutorial is to demonstrate how you can write unit tests for the controllers in your ASP.NET MVC applications. We discuss how to build three different types of unit tests. You learn how to test the view returned by a controller action, how to test the View Data returned by a controller action, and how to test whether or not one controller action redirects you to a second controller action.

Creating the Controller under Test

Let’s start by creating the controller that we intend to test. The controller, named the ProductController, is contained in Listing 1.

Listing 1 – ProductController.cs

usingSystem;
usingSystem.Web.Mvc; namespace Store.Controllers{
public class ProductController:Controller{
public ActionResult Index(){
// Add action logic here
thrownewNotImplementedException();
} public ActionResult Details(intId){
returnView("Details");
} }
}

The ProductController contains two action methods named Index() and Details(). Both action methods return a view. Notice that the Details() action accepts a parameter named Id.

Testing the View returned by a Controller

Imagine that we want to test whether or not the ProductController returns the right view. We want to make sure that when the ProductController.Details() action is invoked, the Details view is returned. The test class in Listing 2 contains a unit test for testing the view returned by the ProductController.Details() action.

Listing 2 – ProductControllerTest.cs

using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Store.Controllers;
namespace StoreTests.Controllers{
[TestClass]
public class ProductControllerTest{
[TestMethod]
public void TestDetailsView(){
var controller =new ProductController();
var result = controller.Details(2)as ViewResult;
Assert.AreEqual("Details", result.ViewName);
}
}
}

The class in Listing 2 includes a test method named TestDetailsView(). This method contains three lines of code. The first line of code creates a new instance of the ProductController class. The second line of code invokes the controller’s Details() action method. Finally, the last line of code checks whether or not the view returned by the Details() action is the Details view.

The ViewResult.ViewName property represents the name of the view returned by a controller. One big warning about testing this property. There are two ways that a controller can return a view. A controller can explicitly return a view like this:

publicActionResultDetails(intId){returnView("Details");}

Alternatively, the name of the view can be inferred from the name of the controller action like this:

publicActionResultDetails(intId){returnView();}

This controller action also returns a view named Details. However, the name of the view is inferred from the action name. If you want to test the view name, then you must explicitly return the view name from the controller action.

You can run the unit test in Listing 2 by either entering the keyboard combination Ctrl-R, A or by clicking the Run All Tests in Solution button (see Figure 1). If the test passes, you’ll see the Test Results window in Figure 2.

Figure 01: Run All Tests in Solution (Click to view full-size image)

 

Figure 02: Success! (Click to view full-size image)

 

Testing the View Data returned by a Controller

An MVC controller passes data to a view by using something called View Data. For example, imagine that you want to display the details for a particular product when you invoke the ProductController Details() action. In that case, you can create an instance of a Product class (defined in your model) and pass the instance to the Details view by taking advantage of View Data.

The modified ProductController in Listing 3 includes an updated Details() action that returns a Product.

Listing 3 – ProductController.cs

using System;
using System.Web.Mvc; namespace Store.Controllers{ public class ProductController:Controller{ public ActionResult Index(){
// Add action logic here
thrownewNotImplementedException();
} public ActionResult Details(intId){
var product =new Product(Id,"Laptop");
return View("Details", product);
}
}
}

First, the Details() action creates a new instance of the Product class that represents a laptop computer. Next, the instance of the Product class is passed as the second parameter to the View() method.

You can write unit tests to test whether the expected data is contained in view data. The unit test in Listing 4 tests whether or not a Product representing a laptop computer is returned when you call the ProductController Details() action method.

Listing 4 – ProductControllerTest.cs

using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Store.Controllers; namespace StoreTests.Controllers{
[TestClass]
public class ProductControllerTest{
[TestMethod]
public void TestDetailsViewData(){
var controller =new ProductController();
var result = controller.Details(2) as ViewResult;
var product =(Product) result.ViewData.Model;
Assert.AreEqual("Laptop", product.Name);
}
}
}

In Listing 4, the TestDetailsView() method tests the View Data returned by invoking the Details() method. The ViewData is exposed as a property on the ViewResult returned by invoking the Details() method. The ViewData.Model property contains the product passed to the view. The test simply verifies that the product contained in the View Data has the name Laptop.

Testing the Action Result returned by a Controller

A more complex controller action might return different types of action results depending on the values of the parameters passed to the controller action. A controller action can return a variety of types of action results including a ViewResult, RedirectToRouteResult, or JsonResult.

For example, the modified Details() action in Listing 5 returns the Details view when you pass a valid product Id to the action. If you pass an invalid product Id -- an Id with a value less than 1 -- then you are redirected to the Index() action.

Listing 5 – ProductController.cs

using System;
using System.Web.Mvc;
namespace Store.Controllers{
public class ProductController:Controller{
public ActionResult Index(){
// Add action logic here
throw new NotImplementedException();
} public ActionResult Details(intId){
if(Id<1)
return RedirectToAction("Index");
var product =newProduct(Id,"Laptop");
returnView("Details", product);
}
}
}

You can test the behavior of the Details() action with the unit test in Listing 6. The unit test in Listing 6 verifies that you are redirected to the Index view when an Id with the value -1 is passed to the Details() method.

Listing 6 – ProductControllerTest.cs

using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Store.Controllers;
namespace StoreTests.Controllers{
[TestClass]p
ublic class ProductControllerTest{
[TestMethod]
public void TestDetailsRedirect(){
var controller =new ProductController();
var result =(RedirectToRouteResult) controller.Details(-1);
Assert.AreEqual("Index", result.Values["action"]);
}
}
}

When you call the RedirectToAction() method in a controller action, the controller action returns a RedirectToRouteResult. The test checks whether the RedirectToRouteResult will redirect the user to a controller action named Index.

Summary

In this tutorial, you learned how to build unit tests for MVC controller actions. First, you learned how to verify whether the right view is returned by a controller action. You learned how to use the ViewResult.ViewName property to verify the name of a view.

Next, we examined how you can test the contents of View Data. You learned how to check whether the right product was returned in View Data after calling a controller action.

Finally, we discussed how you can test whether different types of action results are returned from a controller action. You learned how to test whether a controller returns a ViewResult or a RedirectToRouteResult.

 

[转]Creating Unit Tests for ASP.NET MVC Applications (C#)的更多相关文章

  1. Custom Roles Based Access Control (RBAC) in ASP.NET MVC Applications - Part 1 (Framework Introduction)

    https://www.codeproject.com/Articles/875547/Custom-Roles-Based-Access-Control-RBAC-in-ASP-NET Introd ...

  2. 返璞归真 asp.net mvc (5) - Action Filter, UpdateModel, ModelBinder, Ajax, Unit Test

    原文:返璞归真 asp.net mvc (5) - Action Filter, UpdateModel, ModelBinder, Ajax, Unit Test [索引页] [源码下载] 返璞归真 ...

  3. 【转】ASP.NET MVC 的最佳实践

    [This post is based on a document authored by Ben Grover (a senior developer at Microsoft). It is ou ...

  4. [引]ASP.NET MVC 4 Content Map

    本文转自:http://msdn.microsoft.com/en-us/library/gg416514(v=vs.108).aspx The Model-View-Controller (MVC) ...

  5. Implementing HTTPS Everywhere in ASP.Net MVC application.

    Implementing HTTPS Everywhere in ASP.Net MVC application. HTTPS everywhere is a common theme of the ...

  6. 使用Metrics.NET 构建 ASP.NET MVC 应用程序的性能指标

    通常我们需要监测ASP.NET MVC 或 Web API 的应用程序的性能时,通常采用的是自定义性能计数器,性能计数器会引发无休止的运维问题(损坏的计数器.权限问题等).这篇文章向你介绍一个新的替代 ...

  7. Caching in ASP.NET MVC

    The caching options available in ASP.NET MVC applications don’t come from the ASP.NET MVC Framework, ...

  8. Mixing ASP.NET Webforms and ASP.NET MVC

    https://www.packtpub.com/books/content/mixing-aspnet-webforms-and-aspnet-mvc *********************** ...

  9. How to Choose the Best Way to Pass Multiple Models in ASP.NET MVC

    Snesh Prajapati, 8 Dec 2014 http://www.codeproject.com/Articles/717941/How-to-Choose-the-Best-Way-to ...

随机推荐

  1. ios游戏开发--cocos2d学习(3)

    ------------继续上一节的内容. “接收触摸事件”: CCLayer类是用来接收触摸输入的.不过你要首先启用这个功能才可以使用它. self.isTouchEnabled = YES;//此 ...

  2. 【转载】 Linux用户态和内核态

    [说明]转载自 http://my.oschina.net/liubin/blog/27795 究竟什么是用户态,什么是内核态,这两个基本概念以前一直理解得不是很清楚,根本原因个人觉得是在于因为大部分 ...

  3. HDU-4418 Time travel 概率DP,高斯消元

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4418 题意:简单来说就是给你1个环(n - 1 , n - 2 …… 0 ,1 , 2 , 3 …… ...

  4. 大公司最喜欢问的Java集合类面试题

    看了一些所谓大公司的JAVA面试问题,发现对于JAVA集合类的使用都比较看重似的,而自己在这方面还真的是所真甚少,抽空也学习学习吧. java.util包中包含了一系列重要的集合类,而对于集合类,主要 ...

  5. Visual Studio 2008 – ASP.NET “System.Runtime.InteropServices.COMException”

    The Issue When openning an existing ASP.NET project for the first time in Visual Studio 2008 it retu ...

  6. [iOS基础控件 - 5.2] 查看大图、缩放图片代码(UIScrollView制作)

    原图: 900 x 1305      拖曳滚动:   缩放:           主要代码: // // ViewController.m // ImageZoom // // Created by ...

  7. python os.path模块--转载

    os.path.abspath(path) #返回绝对路径 os.path.basename(path) #返回文件名 os.path.commonprefix(list) #返回list(多个路径) ...

  8. TCP建立连接的3次握手和关闭连接的4次挥手

    #.3次握手过程状态 第一次握手:建立连接时,客户端发送SYN包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认: 第二次握手:服务器收到SYN包,必须确认客户的SYN(ack=j+ ...

  9. 学习和理解C#中的事件

    注:本文系学习笔记. 上一篇文章记录了我对C#中委托的理解.委托实际上是一种类型.可以将一个或多个方法绑定到委托上面,调用委托时,一次执行委托上面绑定的方法.本文要讲述的事件实际上和委托有很深的“感情 ...

  10. datagridview控件--导出Excel

    dataGridView控件可以说很方便的显示了数据,而且对于修改和删除数据也很方便,我在前面的一篇博客中写到了如何去绑定数据到该控件上dataGridView控件--绑定数据方法,今天我将如何将数据 ...