zoukankan      html  css  js  c++  java
  • 为 ASP.NET MVC 应用程序创建单元测试

    为 ASP.NET MVC 应用程序创建单元测试

      from :http://msdn.microsoft.com/zh-cn/dd320293.aspx

    本教程的目的是解释如何为 ASP.NET MVC 应用程序中的控制器编写单元测试。我们将讨论如何创建三种不同类型的单元测试。您将了解如何测试控制器操作返回的视图、如何测试控制器操作返回的视图数据,以及如何测试一个控制器操作是否重定向到另一个控制器操作。

    创建测试控制器

    我们首先创建要测试的控制器。程序清单 1 中包含名称为 ProductController 的控制器。

    程序清单 1 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)
    {
    return View("Details");
    }
    }
    }

    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
    {
    [TestClass]
    public class ProductControllerTest
    {
    [TestMethod]
    public void TestDetailsView()
    {
    var controller = new ProductController();
    var result = controller.Details(2) as ViewResult;
    Assert.AreEqual("Details", result.ViewName);
    }
    }
    }

    程序清单 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。

    测试控制器返回的操作结果

    较复杂的控制器操作可能返回不同类型的操作结果,具体取决于传递给控制器操作的参数值。控制器操作可以返回各种类型的操作结果,包括 ViewResultRedirectToRouteResultJsonResult

    例如,程序清单 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

  • 相关阅读:
    配置类【RibbonAutoConfiguration】的实例属性【configurations】是如何注入的?---实例化
    配置类【RibbonAutoConfiguration】的实例属性【configurations】是如何注入的?---配置类来源
    为什么启动类被【@SpringBootApplication】注解后,就会自动扫描其包内所有被【@Component】注解的类?
    自定义Ribbon配置时出现自定义的扫描排除注解【excludeFilters】不生效
    Spring
    eureka关闭crsf过滤
    docker-compose
    eureka
    centos7根目录扩容的一些理解
    Error injecting: org.apache.maven.artifact.installer.DefaultArtifactInstaller com.google.inject.ProvisionException: Unable to provision
  • 原文地址:https://www.cnblogs.com/no7dw/p/1728859.html
Copyright © 2011-2022 走看看