【问题标题】:How to do unit test for session values?如何对会话值进行单元测试?
【发布时间】:2014-05-21 04:51:11
【问题描述】:

下面是控制器方法(c#)的一段代码:-

public ActionResult SelectProduct(string ProdName, int Block, int ProductAddressId = 0)
{
       if (ProductAddressId == 0 && Block == 1 && System.Web.HttpContext.Current.Session["ReturnProductAddressID"] != null)
       {
           ProductAddressId = (int)System.Web.HttpContext.Current.Session["ReturnProductAddressID"]; 
       }
       //other stuffs………    
}

以下是单元测试方法:-

   [TestMethod]
   public void SelectProduct_Condition1_Test()
   {
       //Arrange
       var controller = new ProductController();

       var prodName = string.Empty;
       var block = 1;
       var productAddressId = 0;

   //section 1
       /*var mockControllerContext = new Mock<ControllerContext>();
       var mockSession = new Mock<HttpSessionStateBase>();
       mockSession.SetupGet(s => s["ReturnProductAddressID"]).Returns("1");
       mockControllerContext.Setup(p => p.HttpContext.Session).Returns(mockSession.Object);*/

  //section 2
       /*int sessionValue = 1;
       var mockControllerContext = new Mock<ControllerContext>();
       var mockSession = new Mock<HttpSessionStateBase>();
       mockSession.SetupSet(s => s["ReturnProductAddressID"] = It.IsAny<int>()).Callback((string name, object val) => sessionValue = (int)val);
       mockSession.SetupGet(s => s["ReturnProductAddressID"]).Returns(() => sessionValue);
       mockControllerContext.Setup(p => p.HttpContext.Session).Returns(mockSession.Object);*/

       //Act         
       var actual = controller.SelectProduct(prodName,block,productAddressId);
 }

我想问我如何在我的操作方法上测试或模拟会话值(在 if 条件下)?

我在第 1 节和第 2 节中尝试了某些东西(上面单元测试方法中的注释部分)。但没有任何效果。

那么谁能告诉我如何对会话进行单元测试?

编辑:

上面的东西没有工作,而不是下面:-

System.Web.HttpContext.Current.Session["ReturnProductAddressID"] = "12";

表示如果我直接在单元测试方法中设置会话值。但我想知道这是正确的方法吗?

【问题讨论】:

标签: c# asp.net-mvc unit-testing moq


【解决方案1】:

您可以使用模拟。这是我以前的做法。

下载更新后的 MoQ https://www.nuget.org/packages/moq

控制器的 Moc 会话

var mockControllerContext = new Mock<ControllerContext>();
var mockSession = new Mock<HttpSessionStateBase>();
mockSession.SetupGet(s => s["ReturnProductAddressID"]).Returns("123"); //somevalue
mockControllerContext.Setup(p => p.HttpContext.Session).Returns(mockSession.Object);

为控制器注册 mockControllerContext

var controller = new YourController();
controller.ControllerContext = mockControllerContext.Object;

最后行动

var actual = controller.SelectProduct(YourModel);

所以,你的代码应该是这样的。

    [TestMethod]
    public void SelectProduct_Condition1_Test()
    {
        var prodName = string.Empty;
        var block = 1;
        var productAddressId = 0;

        var mockControllerContext = new Mock<ControllerContext>();
        var mockSession = new Mock<HttpSessionStateBase>();
        mockSession.SetupGet(s => s["ReturnProductAddressID"]).Returns("123"); //somevalue
        mockControllerContext.Setup(p => p.HttpContext.Session).Returns(mockSession.Object);

        var controller = new ProductController();
        controller.ControllerContext = mockControllerContext.Object;

        //Act         
        var actual = controller.SelectProduct(prodName, block, productAddressId);
    }

【讨论】:

  • ,我已经尝试过了,但是当我在控制器中调试代码时,它显示会话为空。
  • 你注册过ControllerContext对象吗?那应该行得通。 var 控制器 = 新 YourController(); controller.ControllerContext = mockControllerContext.Object;
  • ,是的,我做到了。请检查以下内容:- var controller = new ProductController(); var mockControllerContext = new Mock(); var mockSession = new Mock(); mockSession.SetupGet(s => s["ReturnProductAddressID"]).Returns("4"); //somevalue mockControllerContext.Setup(p => p.HttpContext.Session).Returns(mockSession.Object); controller.ControllerContext = mockControllerContext.Object;
  • 我更新了我的答案,你可以试试那个测试方法吗?
  • ,我再次尝试使用您的代码,但在 if 条件下会话仍然为空(在操作方法中)。
【解决方案2】:

说实话:模拟 Session 变量或通过挂钩到当前会话来使用“真正的交易”总是令人讨厌。当您的代码中有大量 HttpContext.Session 变量时 - 是的,您可以对此发表意见 - 使测试它们变得“困难”。

我的解决方案是尽可能多地使用 ViewBags,并将您想要测试的结果值保留在这些 ViewBags 中,并忽略来自 HttpContext.Session 变量的空错误。如果您真的想测试其中的一些及其值,请将这些值放入 ViewBags 并在您的 viewResult 中进行测试。

通过在我的真实代码中使用适当的 try catch,Session vars 上的空值将被忽略,并且在需要时我会检查 viewResult 中 ViewBags 的值。

这是最好的解决方案吗?可能不会,不,绝对不会,但它让我的步伐继续前进并解决了需求:让控制器运行并密切关注 ViewBags 中我想要的值。

示例代码:

        // Arrange
        TarotCards.Controllers.ProverbsController controller = new 
        TarotCards.Controllers.ProverbsController();

        // Act
        ActionResult result = controller.IndexThrow("KeeperHelp");

        // Assert
        Assert.IsInstanceOfType(result, typeof(ViewResult));
        ViewResult viewResult = result as ViewResult;
        if (viewResult != null)
        {
            string sProverb = viewResult.ViewData["Proverb"].ToString();
            Assert.IsTrue(sProverb.Contains("Help on Keeper"));
            // Assert content of viewResult.
        }

【讨论】:

    猜你喜欢
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 2016-03-18
    • 2011-02-02
    • 2023-03-17
    • 2010-11-22
    • 1970-01-01
    • 2011-09-26
    相关资源
    最近更新 更多