【问题标题】:Unit Test Controller mocking ISession单元测试控制器模拟 ISession
【发布时间】:2019-01-16 12:37:37
【问题描述】:

我想对我的控制器进行单元测试,但在读取来自 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();
  ...
}

【问题讨论】:

    标签: c# asp.net-core mocking moq xunit


    【解决方案1】:

    如果有人有一天会遇到同样的问题,请看:

    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 扩展方法。根据下面的source code 是实现

      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);
      

      我在任何地方都找不到这个,所以在这里分享一下,以防对遇到同样问题的人有所帮助。

      【讨论】:

        猜你喜欢
        • 2012-02-27
        • 2010-10-01
        • 1970-01-01
        • 2015-03-15
        • 2014-07-30
        • 2012-08-01
        • 1970-01-01
        • 2014-01-16
        • 2020-01-05
        相关资源
        最近更新 更多