初始化 DefaultHttpContext.Response.Body 到 MemoryStream 抛出 NullReferencePointer
Initializing DefaultHttpContext.Response.Body to MemoryStream throws NullReferencePointer
我正在研究全局异常中间件的实现,我想用单元测试来覆盖中间件。下面你看看我走了多远。
这是单元测试的代码。
[Fact]
public async Task MethodName_StateUnderTest_ExpectedBehavior()
{
//Arrange
IExceptionHandlerFeature exceptionHandlerFeature = new ExceptionHandlerFeature {Error = new NotFoundException()};
IFeatureCollection features = new FeatureCollection();
features.Set(exceptionHandlerFeature);
var context = new DefaultHttpContext(features);
context.Response.Body = new MemoryStream();
//Act
await ExceptionMiddleware.HandleException(context);
//Assert
context.Response.StatusCode.Should().Be((int) HttpStatusCode.NotFound);
}
这是ExceptionMiddleware.Handle方法的代码
public static async Task HandleException(HttpContext context)
{
var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
if (contextFeature == null)
{
return;
}
if (contextFeature.Error is AppValidationException validationException)
{
context.Response.StatusCode = (int) HttpStatusCode.BadRequest;
var failures = JsonConvert.SerializeObject(validationException.Failures);
await context.Response.WriteAsync(
new ErrorDetails
{
StatusCode = context.Response.StatusCode,
Message = contextFeature.Error.Message,
StackTrace = contextFeature.Error.StackTrace,
Detail = failures
}.ToString());
return;
}
context.Response.StatusCode = (int) ResolveStatusCodeFromExceptionType(contextFeature.Error);
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(
new ErrorDetails
{
StatusCode = context.Response.StatusCode,
Message = contextFeature.Error.Message,
StackTrace = contextFeature.Error.StackTrace
}.ToString());
}
测试在线
context.Response.Body = new MemoryStream();
根据这个,一切都应该没问题,但我仍然无法初始化属性 Body。
测试项目目标框架是.Net Core 3.0。
ExceptionMiddleware.cs 在设置目标框架 .NET Standard 2.1 的项目中,它是 Class 库。
异常的StackTrace真的很短:
at
Microsoft.AspNetCore.Http.Internal.DefaultHttpResponse.set_Body(Stream
value) at
Itixis.Shared.API.Tests.ExceptionMiddlewareTests.d__0.MoveNext()
in
C:\Users\daniel.rusnok\source\repos\Itixis\Itixis.Shared\Tests\Itixis.Shared.API.Tests\ExceptionMiddlewareTests.cs:line
35
通过手动设置功能,您将删除默认设置的功能,这会导致空错误。
public DefaultHttpContext()
: this(new FeatureCollection())
{
Features.Set<IHttpRequestFeature>(new HttpRequestFeature());
Features.Set<IHttpResponseFeature>(new HttpResponseFeature());
Features.Set<IHttpResponseBodyFeature>(new StreamResponseBodyFeature(Stream.Null));
}
public DefaultHttpContext(IFeatureCollection features)
{
_features.Initalize(features);
_request = new DefaultHttpRequest(this);
_response = new DefaultHttpResponse(this);
}
注意默认构造函数中添加的请求、响应和响应主体功能。
要么尝试通过添加所需的功能来重新创建在默认构造函数中完成的操作,
IExceptionHandlerFeature exceptionHandlerFeature = new ExceptionHandlerFeature {Error = new NotFoundException()};
IFeatureCollection features = new FeatureCollection();
features.Set(exceptionHandlerFeature);
features.Set<IHttpRequestFeature>(new HttpRequestFeature());
features.Set<IHttpResponseFeature>(new HttpResponseFeature());
features.Set<IHttpResponseBodyFeature>(new StreamResponseBodyFeature(Stream.Null));
var context = new DefaultHttpContext(features);
//...
或删除手动功能并使用默认构造函数。
[Fact]
public async Task MethodName_StateUnderTest_ExpectedBehavior() {
//Arrange
var context = new DefaultHttpContext();
context.Response.Body = new MemoryStream();
//Act
await ExceptionMiddleware.HandleException(context);
//Assert
context.Response.StatusCode.Should().Be((int) HttpStatusCode.NotFound);
}
它应该按预期工作。
我正在研究全局异常中间件的实现,我想用单元测试来覆盖中间件。下面你看看我走了多远。
这是单元测试的代码。
[Fact]
public async Task MethodName_StateUnderTest_ExpectedBehavior()
{
//Arrange
IExceptionHandlerFeature exceptionHandlerFeature = new ExceptionHandlerFeature {Error = new NotFoundException()};
IFeatureCollection features = new FeatureCollection();
features.Set(exceptionHandlerFeature);
var context = new DefaultHttpContext(features);
context.Response.Body = new MemoryStream();
//Act
await ExceptionMiddleware.HandleException(context);
//Assert
context.Response.StatusCode.Should().Be((int) HttpStatusCode.NotFound);
}
这是ExceptionMiddleware.Handle方法的代码
public static async Task HandleException(HttpContext context)
{
var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
if (contextFeature == null)
{
return;
}
if (contextFeature.Error is AppValidationException validationException)
{
context.Response.StatusCode = (int) HttpStatusCode.BadRequest;
var failures = JsonConvert.SerializeObject(validationException.Failures);
await context.Response.WriteAsync(
new ErrorDetails
{
StatusCode = context.Response.StatusCode,
Message = contextFeature.Error.Message,
StackTrace = contextFeature.Error.StackTrace,
Detail = failures
}.ToString());
return;
}
context.Response.StatusCode = (int) ResolveStatusCodeFromExceptionType(contextFeature.Error);
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(
new ErrorDetails
{
StatusCode = context.Response.StatusCode,
Message = contextFeature.Error.Message,
StackTrace = contextFeature.Error.StackTrace
}.ToString());
}
测试在线
context.Response.Body = new MemoryStream();
根据这个
测试项目目标框架是.Net Core 3.0。 ExceptionMiddleware.cs 在设置目标框架 .NET Standard 2.1 的项目中,它是 Class 库。
异常的StackTrace真的很短:
at Microsoft.AspNetCore.Http.Internal.DefaultHttpResponse.set_Body(Stream value) at Itixis.Shared.API.Tests.ExceptionMiddlewareTests.d__0.MoveNext() in C:\Users\daniel.rusnok\source\repos\Itixis\Itixis.Shared\Tests\Itixis.Shared.API.Tests\ExceptionMiddlewareTests.cs:line 35
通过手动设置功能,您将删除默认设置的功能,这会导致空错误。
public DefaultHttpContext()
: this(new FeatureCollection())
{
Features.Set<IHttpRequestFeature>(new HttpRequestFeature());
Features.Set<IHttpResponseFeature>(new HttpResponseFeature());
Features.Set<IHttpResponseBodyFeature>(new StreamResponseBodyFeature(Stream.Null));
}
public DefaultHttpContext(IFeatureCollection features)
{
_features.Initalize(features);
_request = new DefaultHttpRequest(this);
_response = new DefaultHttpResponse(this);
}
注意默认构造函数中添加的请求、响应和响应主体功能。
要么尝试通过添加所需的功能来重新创建在默认构造函数中完成的操作,
IExceptionHandlerFeature exceptionHandlerFeature = new ExceptionHandlerFeature {Error = new NotFoundException()};
IFeatureCollection features = new FeatureCollection();
features.Set(exceptionHandlerFeature);
features.Set<IHttpRequestFeature>(new HttpRequestFeature());
features.Set<IHttpResponseFeature>(new HttpResponseFeature());
features.Set<IHttpResponseBodyFeature>(new StreamResponseBodyFeature(Stream.Null));
var context = new DefaultHttpContext(features);
//...
或删除手动功能并使用默认构造函数。
[Fact]
public async Task MethodName_StateUnderTest_ExpectedBehavior() {
//Arrange
var context = new DefaultHttpContext();
context.Response.Body = new MemoryStream();
//Act
await ExceptionMiddleware.HandleException(context);
//Assert
context.Response.StatusCode.Should().Be((int) HttpStatusCode.NotFound);
}
它应该按预期工作。