簡體   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