单元测试控制器模拟ISession

6
我想对我的控制器进行单元测试,但是我在读取HttpContext.Session的值时遇到了问题。
我想要模拟控制器中的这一部分:HttpContext.Session.Get<int>(Foo) 通过Mock HttpContext for unit testing a .NET core MVC controller?How to mock Session Object in asp net core,我得出了以下解决方案:
我的测试:
public void GetFoos_AllGood_ReturnList()
{
  //Arrange
  Mock<ISession> sessionMock = new Mock<ISession>();
  var fooSessionValue = new byte[0];

  Web.Controllers.FooController fooController = new Web.Controllers.FooController();
  fooController.ControllerContext.HttpContext = new DefaultHttpContext();
  fooController.ControllerContext.HttpContext.Request.Headers["Foo"] = 0;

  Mock<IServiceCollection> mock = new Mock<IServiceCollection>();
  mock.Object.AddSession(); // Tried this, but failed

  //Setup
  sessionMock.Setup(_ => _.Set("Foo", It.IsAny<byte[]>())).Callback<string, byte[]>((k, v) => fooSessionValue = v);
  sessionMock.Setup(_ => _.TryGetValue("Foo", out fooSessionValue)).Returns(true);
  mockWebDataManager.Setup(b => b.GetFoos(It.IsAny<FooArgs>())).Returns(new FooResult() { Foos = new List<Foo>() });

  //Act
  var result = fooController.GetFoos() as JsonResult;

  //Assert
  Assert.NotNull(result);
  Assert.Equal(200, result.StatusCode);
}

我的控制器:

internal virtual DataArgs CreateArgs()
{
  return new FooArgs
  {
     HttpContext.Session.Get<int>(Foo) // I want to Mock this value    
  };
}

[HttpGet]
public IActionResult GetFoos()
{
  FooArgs args = CreateArgs();
  ...
}
2个回答

5

如果有人今后遇到同样的问题,这里是解决方法:

public void GetFoos_AllGood_ReturnList()
{
  //Arrange
  Mock<ISession> sessionMock = new Mock<ISession>();

  Web.Controllers.FooController fooController = new Web.Controllers.FooController();
  fooController.ControllerContext.HttpContext = new DefaultHttpContext();
  fooController.ControllerContext.HttpContext.Request.Headers["Foo"] = 0; 
  fooController.ControllerContext.HttpContext.Session = sessionMock.Object;

  //Act
  var result = fooController.GetFoos() as JsonResult;

  //Assert
  Assert.NotNull(result);
}

2
感谢Hypernate的回答,但在我的情况下,我必须处理单元测试中的GetInt32和SetInt32扩展方法。根据下面的源代码实现。
public static void SetInt32(this ISession session, string key, int value)
        {
            var bytes = new byte[]
            {
                (byte)(value >> 24),
                (byte)(0xFF & (value >> 16)),
                (byte)(0xFF & (value >> 8)),
                (byte)(0xFF & value)
            };
            session.Set(key, bytes);
        }

public static int? GetInt32(this ISession session, string key)
        {
            var data = session.Get(key);
            if (data == null || data.Length < 4)
            {
                return null;
            }
            return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
        }

所以按照答案中提到的,我需要做一些修改如下来处理它。

 Mock<ISession> sessionMock = new Mock<ISession>();
        var key = "FY";
        int fy = 2020;
        var value =  new byte[]
        {
            (byte)(fy >> 24),
            (byte)(0xFF & (fy >> 16)),
            (byte)(0xFF & (fy >> 8)),
            (byte)(0xFF & fy)
        };

  sessionMock.Setup(_ => _.TryGetValue(key, out value)).Returns(true);

我在其他地方找不到这个信息,所以在这里分享,以帮助遇到相同问题的人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接