【问题标题】:Inspect DefaultHttpContext body in unit test situation在单元测试情况下检查 DefaultHttpContext 主体
【发布时间】:2018-02-08 02:53:13
【问题描述】:

我正在尝试使用 DefaultHttpContext 对象对我的异常处理中间件进行单元测试。

我的测试方法如下:

[Fact]
public async Task Invoke_ProductionNonSuredException_ReturnsProductionRequestError()
{
    var logger = new Mock<ILogger<ExceptionHandlerMiddleware>>();
    var middleWare = new ExceptionHandlerMiddleware(next: async (innerHttpContext) =>
    {
        await Task.Run(() =>
        {
            throw new Exception();
        });
    }, logger: logger.Object);

    var mockEnv = new Mock<IHostingEnvironment>();
    mockEnv.Setup(u => u.EnvironmentName).Returns("Production");

    var context = new DefaultHttpContext();

    await middleWare.Invoke(context, mockEnv.Object);

    var reader = new StreamReader(context.Response.Body);
    var streamText = reader.ReadToEnd();

    //TODO: write assert that checks streamtext is the expected production return type and not the verbose development environment version.
}

在我的中间件中,我正在写这样的上下文:

public static Task WriteResponse(HttpContext context, HttpStatusCode statusCode, object responseData, Formatting jsonFormatting)
{
    context.Response.ContentType = "application/json";
    context.Response.StatusCode = (int)statusCode;
    return context.Response.WriteAsync(JsonConvert.SerializeObject(responseData, jsonFormatting));
}

为了让您更深入地了解我采用的中间件方法,我采用了this answer here 中的方法。

当应用程序运行它是正常的管道时工作正常。但是,在测试中使用 DefaultHttpContext 方法时,响应正文总是返回为空,并且 ContentLength 为空。因此,我在测试中的streamText 变量是一个空字符串。

在这种情况下是否可以检查中间件正在写入上下文的内容?这是合适的方式,还是有更好的方式。

【问题讨论】:

  • 你的 middleWare.Invoke() 发生了什么?也许你只是不在那里调用 WriteResponse()。

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


【解决方案1】:

考虑自己设置主体,以便您可以控制流

@AndrewStanton-Nurse 提供的评论

DefaultHttpContext 中的Response.Body 流是Stream.Null,这是一个忽略所有读/写的流。调用方法前需要自己设置Stream。

进一步 - 这将允许设置正文,但为了正确读取它,我们必须在使用 StreamReader 之前按照this answer 将指针设置为开头。

//...code removed for brevity

var context = new DefaultHttpContext();
context.Response.Body = new MemoryStream();

await middleWare.Invoke(context, mockEnv.Object);


context.Response.Body.Seek(0, SeekOrigin.Begin);
var reader = new StreamReader(context.Response.Body);
var streamText = reader.ReadToEnd();

//...code removed for brevity

【讨论】:

  • 这就是解决方案。 DefaultHttpContext 中的 Body 流是 Stream.Null,它是一个忽略所有读/写的流。调用方法前需要自己设置Stream。
猜你喜欢
  • 2023-01-09
  • 2017-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-30
相关资源
最近更新 更多