如何对会话值进行单元测试

本文关键字:单元测试 会话 | 更新日期: 2023-09-27 17:57:27

下面是控制器方法(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";

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

如何对会话值进行单元测试

您可以使用Mock。以下是我以前的做法。

下载更新的MoQhttps://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);
    }

老实说:嘲笑会话变量或通过连接到当前会话来使用"真正的交易"一直很难做到。当你的代码中有很多HttpContext.Session变量时,是的,你可以对此有意见,这使得测试它们变得"困难"。

我的解决方案是尽可能多地使用ViewBags,并将您想要测试的结果值保留在这些ViewBags中,并忽略HttpContext.Session变量中的null错误。如果你真的想测试其中的一些及其值,那么把这些值放在ViewBags中,然后在你的viewResult中测试它们。

通过在我的真实代码中使用正确的try-catch,Session vars上的null将被忽略,并且在需要时,我将在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.
        }