如何使用ASP.NET 5(MVC 6)中的Response属性对控制器动作进行单元测试? [英] How to unit test a Controller action using the Response property in ASP.NET 5 (MVC 6)?

查看:103
本文介绍了如何使用ASP.NET 5(MVC 6)中的Response属性对控制器动作进行单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In an ASP.NET Core 1.0 (MVC 6) project I have a Controller action method in which I use the Response property to set a header:

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

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

    ...
}

我尝试为此操作方法实施单元测试,但是Response属性的值为空.

I tried to implement a unit test for this action method, but the value of the Response property is null.

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

This was easy to solve in the previous versions of ASP.NET, because the Response property had a setter, and you could simply set its value to a new HttpResponse instance during a unit test.

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

But in ASP.NET 5 Response does not have a setter, only a getter.
How can I set a value for Response in a unit test?

更新:明确地说:这个问题与 ASP.NET Core 1.0 有关.链接为重复项的另一个问题是有关ASP.NET 4的,此后更改了Api,因此该答案不适用于该问题.

UPDATE: Just to make clear: this question is about ASP.NET Core 1.0. The other question linked as duplicate is about ASP.NET 4, and the Api changed since then so the answer there does not apply to this question.

推荐答案

我找到了解决该问题的一种方法,但是它有些繁琐且令人费解,因此,我仍然希望看到一种更简单的方法(如果有).

I found one solution to the problem, however, it's a bit tedious and convoluted, so I'm still interested in seeing a simpler approach, if any exists.

ControllerActionContext.HttpContext获取其Response属性的值.使得模拟变得如此困难的原因在于所有这些属性都是只读的,因此我们不能仅设置模拟值,而必须为游戏中的每个对象创建模拟.

The Controller gets the value of its Response property from ActionContext.HttpContext. What makes mocking this difficult is that all these properties are read-only, so we cannot just simply set a mock value, we have to create mocks for every object in play.

我在测试中需要的部分响应是Headers集合,因此我必须创建并使用以下模拟来使该可用性可用. (通过 Moq 完成模拟.)

The part of the Response I needed in my test was the Headers collection, so I had to create and use the following mocks to make that availale. (Mocking is done with 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
};

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

This is a bit more code than what I'd like to see to mock a single property, but I couldn't find any better approach yet, and it seems to be working nicely.

这篇关于如何使用ASP.NET 5(MVC 6)中的Response属性对控制器动作进行单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆