繁体   English   中英

如何编写带有以下代码段的单元测试以测试ASP.NET MVC控制器

[英]How can I write unit test to test a ASP.NET MVC controller with the following code snippet

所有这些视图甚至都没有标题。 所以我不能

Assert.AreEqual( “错误”,Viewbag.Title);

我还能如何测试错误控制器以确保覆盖至少 85%的代码

public class ErrorController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult NotFound()
    {
        return View();
    }
    public ActionResult BadRequest()
    {
        return View();
    }

    public ActionResult ServerError()
    {
        return View();
    }
}

我能想到的最好的是

public class ErrorControllerTests : BaseTestController
{
    ErrorController ec = new ErrorController();
    [TestMethod()]
    public void IndexTest()
    {
        var actionResult = ec.Index() as ViewResult;

        Assert.AreSame(ec.ViewData, actionResult.ViewData);
        Assert.AreSame(ec.TempData, actionResult.TempData);

        Assert.AreEqual(actionResult.ViewName,"");
    }

    [TestMethod()]
    public void NotFoundTest()
    {
        var NotFoundTestResult = ec.NotFound() as ViewResult;
        Assert.AreEqual(NotFoundTestResult.ViewName,"");
    }

    [TestMethod()]
    public void BadRequestTest()
    {
        var badRequestTestResult = ec.BadRequest() as ViewResult;
        Assert.AreEqual(badRequestTestResult.ViewName,"");
    }

    [TestMethod()]
    public void ServerErrorTest()
    {
        var serverErrorTestResult = ec.ServerError() as ViewResult;
        Assert.AreEqual(serverErrorTestResult.ViewName, "");
    }
}

您可以测试例如视图名称:

Assert.AreEqual("Index", result.ViewName);

但要做到这一点,您需要在操作return中指定视图名称:

public class ErrorController : Controller 
{
        public ActionResult Index()
        {
            return View("Index");
        }

        public ActionResult NotFound()
        {
            return View("NotFound");
        }
        public ActionResult BadRequest()
        {
            return View("BadRequest");
        }

        public ActionResult ServerError()
        {
            return View("ServerError");
        }
    }

您基本上是在尝试测试框架,而拥有该框架的Microsoft应该已经完成​​了测试。 您应该避免测试您不拥有或控制的代码。

就是说,这里是一种测试ErrorController的变通办法,它试图模仿框架功能并解决有关单元测试的限制。

[TestClass]
public class ErrorControllerTests {
    [TestMethod]
    public void TestIndexView() {
        //Arrange
        var expectedViewName = GetViewNameFromExpression<ErrorController>(c => c.Index());
        var controller = ArrangeErrorController(expectedViewName);

        //Act
        var result = controller.Index() as ViewResult;

        //Assert
        Assert.IsNotNull(result);

        //Replicating Framework functionality
        MockExecuteResult(controller, result);

        Assert.AreEqual(expectedViewName, result.ViewName);
        CollectionAssert.AreEquivalent(controller.ViewData.ToList(), result.ViewData.ToList());
        CollectionAssert.AreEquivalent(controller.TempData.ToList(), result.TempData.ToList());
    }

    private static void MockExecuteResult(ErrorController controller, ViewResult result) {
        try {
            result.View = Mock.Of<IView>();
            result.ExecuteResult(controller.ControllerContext);
        } catch { }
    }

    private static ErrorController ArrangeErrorController(string actionName) {
        var controllerName = "error";
        var context = GetControllerContext(actionName, controllerName);
        var controller = new ErrorController() {
            ControllerContext = context
        };
        context.Controller = controller;
        return controller;
    }

    private static ControllerContext GetControllerContext(string actionName, string controllerName) {
        RouteData rd = new RouteData();
        rd.Values["action"] = actionName;
        rd.Values["controller"] = controllerName;

        var mockHttpContext = new Mock<HttpContextBase>();
        mockHttpContext.Setup(c => c.Session).Returns((HttpSessionStateBase)null);
        mockHttpContext.Setup(_ => _.Response.Output).Returns(new StringWriter());

        return new ControllerContext(mockHttpContext.Object, rd, new Mock<Controller>().Object);
    }

    private static string GetViewNameFromExpression<TController>(Expression<Action<TController>> action) {
        if (action == null) {
            throw new ArgumentNullException("action");
        }

        var type = typeof(TController);

        bool isController = type != null
               && type.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)
               && !type.IsAbstract
               && typeof(IController).IsAssignableFrom(type);

        if (!isController) {
            throw new InvalidOperationException("Invalid controller.");
        }

        MethodCallExpression body = action.Body as MethodCallExpression;
        if (body == null)
            throw new InvalidOperationException("Expression must be a method call.");

        if (body.Object != action.Parameters[0])
            throw new InvalidOperationException("Method call must target lambda argument.");

        string actionName = body.Method.Name;
        return actionName;
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM