模拟HttpContext来对.NET核心MVC控制器进行单元测试?


94

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

我的控制器函数期望“ 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);
}

有没有使用第三方库的简单方法?


1
使用HttpContext吗?使用控制器的全部要点是数据来自控制器的参数。如果您的控制器像使用WebForms页面一样使用HttpContext读取数据,则您有问题。
Panagiotis Kanavos '16

@PanagiotisKanavos标头中的值是一条信息,指示呼叫来自哪个移动设备。检索正确的数据是必要的。设备ID在标头中,因为身份验证需要该ID,该ID由自定义操作过滤器处理。我可以将设备ID作为路由参数传递,但这将是多余的
James Wierzba,2016年

检查FromHeaderAttribute,但还要检查重复项。HttpContext现在可以通过配置
注入

1
我建议您编辑问题以准确指定您要的内容(访问标题字段以标识移动设备)。总而言之,ASP.NET文档似乎正经历一个..“过渡”时期,缺少文档页面。检查这个几乎相同的问题,询问如何路由移动设备
Panagiotis Kanavos

Answers:


226

我能够以这种方式初始化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
    ...
}

21

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

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

虽然您可以模拟HttpContext,但在我看来,除非没有选择,否则应避免这种情况。FromHeaderAttribute的文档可以在FromHeaderAttribute Class中找到。

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

1
在我的情况下,IIRC要求将其包含在http标头中,因为需要在.net核心中间件组件中评估相同的值
James Wierzba
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.