【发布时间】:2018-10-20 23:08:44
【问题描述】:
我在一个 ASP.NET Core 站点中编写了一些中间件,我正在尝试对其进行单元测试,主要是通过关注使用 Moq 的 this guide。
我的问题是找到一个与new DefaultHttpContext() 等效的 NUnit/NSubstitute。替换 HttpContext 会触发中间件,但是它通过了try。我认为这是因为下面引用的问题。 NUnit 是否具有创建真实 HttpContext 的功能,还是我正在寻找更多的基础设施来实现这一点?
我正在向 Invoke 方法发送一个 DefaultHttpContext 实例。在这种情况下,我不能使用模拟的 HttpContext,因为第一个中间件(我们传递给构造函数的 lambda 函数)需要写入响应。因此 HttpResponse 需要是一个没有被模拟的真实对象。
这是我的测试代码
[TestFixture]
public class ExceptionHelperTests
{
private IErrorRepository errorRepository;
private ExceptionHandler handler;
[SetUp]
public void Setup()
{
errorRepository = Substitute.For<IErrorRepository>();
}
[Test]
public async void Given_AnExceptionHappens_Then_ItShouldBeLogged()
{
// Arrange
const string username = "aUser";
var user = Substitute.For<ClaimsPrincipal>();
user.Identity.Name.Returns(username);
handler = new ExceptionHandler(
next: async (innerHttpContext) =>
{
innerHttpContext.User = user;
},
repository: errorRepository);
// Act
await handler.Invoke(new DefaultHttpContext());
// Assert
errorRepository.Received().LogException(Arg.Any<string>(), Arg.Any<Exception>(), Arg.Is(username));
}
}
这里是 IErrorRepository
public interface IErrorRepository
{
Exception LogException(string message, Exception ex, string userId);
void LogMessage(string message, string errorDetail, string userId);
}
这里是中间件(带有简化的 HandleException):
public sealed class ExceptionHandler
{
private readonly RequestDelegate _next;
private readonly IErrorRepository repository;
public ExceptionHandler(RequestDelegate next, IErrorRepository repository)
{
_next = next;
this.repository = repository;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
HandleException(ex, context.User.Identity.Name);
}
}
public void HandleException(Exception ex, string userId)
{
repository.LogException("An unhandled exception has occurred.", ex, userId);
}
}
【问题讨论】:
-
DefaultHttpContext是 .net 核心的一部分,而不是测试框架。问题是什么?目前的解释还不清楚。 -
同时避免
async void。如果进行 TAP,请进行测试async Task -
您能否也显示正在测试的方法以使问题成为minimal reproducible example
-
我已经添加了中间件代码。我原本认为它是一个严格的设计没有帮助,但也许我错了。
标签: unit-testing asp.net-core nunit middleware nsubstitute