【问题标题】:Unit Testing a RedirectToAction with parameter使用参数对 RedirectToAction 进行单元测试
【发布时间】:2016-07-13 23:55:13
【问题描述】:

我有一个 MVC 控制器类,我正在尝试对其进行单元测试。

具体的ActionResult是这样的

public ActionResult Create(Shipment newShipment)
{
   do some stuff to create a shipmentID
...
   return RedirectToAction("AddUnit",newShipment.ShipmentID);
}

我已经模拟了控制器上下文等,现在我想测试传递给 RedirectToAction 调用的 newShipment.ShipmentID 是否符合我的预期。

我有一个测试(在设置阶段有很多模拟)

    [Test]
    public void CreateSuccess()
    {
        //Arrange
        var shipment = new Shipment();
        shipment.Widgets = 2; //Make sure it a valid shipment otherwise
        //Act
        var result = controller.Create(shipment) as RedirectToRouteResult;
        //Assert
        Assert.IsNotNull(result);
        Assert.AreEqual("AddUnits", result.RouteValues["action"]);
        Assert.IsNull(result.RouteValues["controller"]);
        ...

现在我想找到一个 Assert 来检查我传递给 RedirectToAction 的 shippingID 是否正确。如何检索它的值?

(我相信这段代码确实有效(即实际视图得到正确的shipmentID)但我想编写一个单元测试)。

【问题讨论】:

  • 你能改变 Create 函数以通过引用传递参数,如下所示:public ActionResult Create(ref Shipment newShipment)?如果是这样,您可以简单地 Do Assert.IsEqual(shipment.shipmentID, yourvalue);
  • 我对 Create 函数的调用方式没有太多控制 - 这是 ASP.NET MVC 及其在实际应用程序中调用 create 的框架。
  • 我想我可能弄错了 RedirectToAction 携带参数的能力——我认为它们进入了 TempData。无论如何,最后我重新设计了控制器以返回一个视图。

标签: asp.net-mvc nunit


【解决方案1】:

其实RedirectToActions可以带参数;下面是我如何在一个中测试正确参数的简化示例。我在这里使用 NUnit 和 FluentAssertions。

[HttpPost]        
public ActionResult RedirectMethod()
{
     return RedirectToAction("Index", "Home", new { parameter = "Value" });
}

然后是测试:

[Test]
public void RedirectSetsExpectedParameters()
{
    var result = controller.RedirectMethod();
    var redirectResult = result.As<RedirectToRouteResult>();

    var expectedRedirectValues = new RouteValueDictionary
        {
            { "parameter", "Value" },
            { "action", "Index" },
            { "controller", "Home" }
        };

    redirectResult
       .RouteValues
       .ShouldBeEquivalentTo(expectedRedirectValues, 
       "The redirect should look as I expect, including the parameters");
}

【讨论】:

  • 感谢您努力回答我将近 3 年的问题。它是很久以前的技术了,因为我不知道你的答案的相关性或正确性,所以我没有使用过。
  • 别担心!我只是为了后代添加它,因为我最近试图解决同样的问题。
【解决方案2】:

这里我给出了一个重定向到操作的示例

public ActionResult Signupsuccess(string account_code, string plan)
{
   ..........
  do some stuff

  return RedirectToAction("SubscriptionPlan", "Settings");

}

我已经模拟了控制器上下文并将一些参数传递给从控制器到测试方法的 RedirectToAction 调用。最后它测试了预期和实际

[TestMethod()]

 public void SignupsuccessTest()
       {
            HomeController target = new HomeController(); // TODO: Initialize to an appropriate value
            string account_code = "B898YB7"; // TODO: Initialize to an appropriate value
            string plan = "Application-BASIC"; // TODO: Initialize to an appropriate value

            var ControllerContext = new Mock<ControllerContext>();
            var context = target.HttpContext;

            ControllerContext.SetupGet(p => p.HttpContext.Session["MerchantID"]).Returns("15");
            ControllerContext.SetupGet(p => p.HttpContext.Session["FriendlyIdentifier"]).Returns("3d649876-19f5-48d2-af03-ca89083ae712");

            target.ControllerContext = controllerContext.Object;       

            var action = (RedirectToRouteResult)target.Signupsuccess(account_code, plan);

            action.RouteValues["action"].Equals("SubscriptionPlan");
            action.RouteValues["controller"].Equals("Settings");

            Assert.AreEqual("SubscriptionPlan", action.RouteValues["action"]);
            Assert.AreEqual("Settings", action.RouteValues["controller"]);          
        }

希望对你有帮助。谢谢

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-29
    • 1970-01-01
    • 2011-08-22
    • 2015-08-20
    • 1970-01-01
    • 2017-12-16
    相关资源
    最近更新 更多