模拟HttpContext用于单元测试.NET核心MVC控制器?

时间:2016-12-30 17:15:23

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

我在控制器中有一个函数,我正在进行单元测试,期望http请求标头中的值。我无法初始化HttpContext,因为它只是readonly。

我的控制器功能需要" device-id"

的http请求标头值
[TestMethod]
public void TestValuesController()
{
    ValuesController controller = new ValuesController();

    //not valid controller.HttpContext is readonly
    //controller.HttpContext = new DefaultHttpContext(); 

    var result = controller.Get();
    Assert.AreEqual(result.Count(), 2);
}

在没有使用第三方库的情况下,有没有直接的方法呢?

2 个答案:

答案 0 :(得分:142)

我能够以这种方式初始化httpcontext和标题:

[TestMethod]
public void TestValuesController()
{
    ValuesController controller = new ValuesController();
    controller.ControllerContext = new ControllerContext();
    controller.ControllerContext.HttpContext = new DefaultHttpContext();
    controller.ControllerContext.HttpContext.Request.Headers["device-id"] = "20317";
    var result = controller.Get();
    //the controller correctly receives the http header key value pair device-id:20317
    ...
}

答案 1 :(得分:13)

不是嘲笑HTTPContext,而是将标题映射到方法上的参数可能更好。例如,在此答案底部的控制器中,id参数设置为值标题,其名称等于“device-id”...然后单元测试变为

[TestMethod]
public void TestValuesController()
{
    ValuesController controller = new ValuesController();
    var result = controller.GetHeaderValue("27");
    Assert.AreEqual(result, "27");
}

虽然可以模仿HttpContext,但在我看来,除非你别无选择,否则应该避免这种情况。可以在FromHeaderAttribute Class找到FromHeaderAttribute的文档。

    public class ValuesController: Controller
    {

      public string GetHeaderValue([FromHeader(Name = "device-id")] string id)
      {
        return id;
      }
    }