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