通常在我们使用visualstudiao 2010创建mvc项目的时候,默认的状态下就可以创建测试单元。但是,在有些情况下,我们没有创建测试单元,后来就需要测试单元的时候,我们就可以通过以下三种方式进行添加。本文章转自网络。
本教程的目的是解释如何为 ASP.NET MVC 应用程序中的控制器编写单元测试。我们将讨论如何创建三种不同类型的单元测试。您将了解如何测试控制器操作返回的视图、如何测试控制器操作返回的视图数据,以及如何测试一个控制器操作是否重定向到另一个控制器操作。
创建测试控制器
我们首先创建要测试的控制器。程序清单 1 中包含名称为 ProductController 的控制器。
程序清单 1 ProductController.cs
using System; using System.Web.Mvc; namespace Store.Controllers public ActionResult Details(int Id) |
HomeController 包含两个操作方法,名称为 Index() 和 Details()。两个操作方法都返回一个视图。请注意, Details() 操作接受名称为 Id 的参数。
测试控制器返回的视图
假设要测试 ProductController 是否返回正确的视图。希望确保当激活 ProductController.Details() 操作时,返回 Details 视图。程序清单 2 中的测试类包含一个单元测试,用于测试由 ProductController.Details() 操作返回的视图。
程序清单 2 ProductControllerTest.cs
using System.Web.Mvc; using Microsoft.VisualStudio.TestTools.UnitTesting; using Store.Controllers; namespace StoreTests.Controllers |
程序清单 2 中的类包含名称为 TestDetailsView() 的测试方法。此方法包括三行代码。第一行代码创建一个 ProductController 类的新实例。第二行代码激活控制器的 Details() 操作方法。最后一行代码检查 Details() 操作返回的是否是 Details 视图。
ViewResult.ViewName 属性代表由控制器返回的视图的名称。测试该属性时需要特别小心。控制器返回视图有两种方法。控制器可以显式地返回视图,如下所示:
public ActionResult Details(int Id) { return View("Details"); } |
另外,视图的名称可以引用控制器操作的名称,如下所示:
public ActionResult Details(int Id) { return View(); } |
此控制器操作也返回名称为 Details 的视图。然而,视图的名称引用自操作的名称。如果想要测试视图名称,则必须显式地从控制器操作返回视图名称。
通过按 Ctrl-R,A 组合键或单击 Run All Tests in Solution 按钮(如图 1 所示),可以运行程序清单 2 中的单元测试。如果通过测试,则将看到如图 2 所示的 Test Results 窗口。
图 1:运行解决方案中的所有测试
图 2:成功!
测试控制器返回的 View Data
MVC 控制器使用 View Data 将数据传递给视图。例如,假设想要在激活 ProductController Details() 操作时显示某个产品的详细信息。在这种情况下,可以创建 Product 类的实例(在模型中定义),然后利用 View Data 将实例传递给 Details 视图。
程序清单 3 中修改后的 ProductController 包含更新的 Details() 操作,它返回 Product。
程序清单 3 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(int Id) { var product = new Product(Id, "Laptop"); return View("Details", product); } } } |
首先,Details() 操作创建 Product 类的新实例表示笔记本电脑。接下来,Product 类的实例被作为第二个参数传递给 View() 方法。
可以编写测试单元测试预期的数据是否包含在视图数据中。程序清单 4 中的单元测试用于测试表示笔记本电脑的 Product 是否在调用 ProductController Details() 操作方法时返回。
程序清单 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); } } } |
在程序清单 4 中,TestDetailsView() 方法通过激活 Details() 方法测试返回的 View Data。ViewData 公开为 ViewResult(通过激活 Details() 方法返回)上的一个属性。ViewData.Model 属性包含传递给视图的产品。测试只是简单地验证包含在 View Data 中的产品名称是 Laptop。
测试控制器返回的操作结果
较复杂的控制器操作可能返回不同类型的操作结果,具体取决于传递给控制器操作的参数值。控制器操作可以返回各种类型的操作结果,包括 ViewResult、RedirectToRouteResult 或 JsonResult。
例如,程序清单 5 中修改的 Details() 操作在将有效 Id 传递给操作时返回 Details 视图。如果传递无效的产品 Id(Id 的值小于 1),则将重定向到 Index() 操作。
程序清单 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(int Id) { if (Id < 1) return RedirectToAction("Index"); var product = new Product(Id, "Laptop"); return View("Details", product); } } } |
可以使用程序清单 6 中的单元测试来测试 Details() 操作的行为。程序清单 6 中的单元测试验证当 Id 值 -1 被传递到 Details() 方法时是否重定向到 Index 视图。
程序清单 6 ProductControllerTest.cs
using System.Web.Mvc; using Microsoft.VisualStudio.TestTools.UnitTesting; using Store.Controllers; namespace StoreTests.Controllers { [TestClass] public class ProductControllerTest { [TestMethod] public void TestDetailsRedirect() { var controller = new ProductController(); var result = (RedirectToRouteResult) controller.Details(-1); Assert.AreEqual("Index", result.Values["action"]); } } } |
在调用控制器操作的 RedirectToAction() 方法时,控制器操作返回 RedirectToRouteResult。测试用于检查 RedirectToRouteResult 是否将用户重定向到名称为 Index 的控制器操作。
总结
在本教程中,我们学习了如何为 MVC 控制器操作构建单元测试。首先,我们学习了如何验证控制器操作是否返回正确的视图。学习了如何使用 ViewResult.ViewName 属性验证视图的名称。
接下来,我们研究了如何测试 View Data 的内容。学习了如何检查调用控制器操作后 View Data 中是否返回正确的产品。
最后,我们讨论了如何测试控制器操作是否返回不同类型的操作结果。学习了如何测试控制器操作是返回 ViewResult 还是 RedirectToRouteResult。