如何使用ASP.NET 5(MVC 6)中的Response属性对Controller操作进行单元测试?

Mar*_*cze 8 c# asp.net asp.net-core-mvc asp.net-core

ASP.NET Core 1.0(MVC 6)项目中,我有一个Controller操作方法,我在其中使用该Response属性来设置标头:

[HttpGet]
public IActionResult Get()
{
    ...

    Response.Headers.Add("Location", location);

    ...
}
Run Code Online (Sandbox Code Playgroud)

我尝试为此操作方法实现单元测试,但该Response属性的值为null.

这在以前的ASP.NET版本中很容易解决,因为该Response属性具有setter,您可以HttpResponse在单元测试期间将其值设置为新实例.

但是在ASP.NET 5 Response中没有setter,只有一个getter.
如何Response在单元测试中设置值?

更新:只是说清楚:这个问题是关于ASP.NET Core 1.0.另一个链接为重复的问题是关于ASP.NET 4,从那以后Api发生了变化,所以那里的答案不适用于这个问题.

Mar*_*cze 14

我找到了一个问题的解决方案,然而,它有点乏味和复杂,所以我仍然有兴趣看到一个更简单的方法,如果有的话.

Controller得到它的价值Response物业ActionContext.HttpContext.嘲笑这个困难的原因是所有这些属性都是只读的,所以我们不能简单地设置一个模拟值,我们必须为每个游戏中的对象创建模拟.

我在测试中需要的响应部分是Headers集合,因此我必须创建并使用以下模拟来实现这一点.(模拟是用Moq完成的.)

var sut = new MyController();

// The HeaderDictionary is needed for adding HTTP headers to the response.
// This needs a couple of different Mocks, because many properties in the class model are read-only.
var headerDictionary = new HeaderDictionary();
var response = new Mock<HttpResponse>();
response.SetupGet(r => r.Headers).Returns(headerDictionary);

var httpContext = new Mock<HttpContext>();
httpContext.SetupGet(a => a.Response).Returns(response.Object);

sut.ActionContext = new ActionContext()
{
    HttpContext = httpContext.Object
};
Run Code Online (Sandbox Code Playgroud)

这比我想要模拟单个属性的代码要多一些,但是我找不到更好的方法,而且它看起来效果很好.

  • 万一有人还在看这个.`Microsoft.AspNetCore.Mvc.Controller`中不存在`ActionContext`.它已被`ControllerContext`引用取代:http://stackoverflow.com/questions/37286530/actioncontext-gone-in-microsoft-aspnetcore-mvc-controller (7认同)