Я написал немного Middleware на сайте AspNetCore, и я пытаюсь провести его модульное тестирование, в основном, следуя этому руководству , в котором используется Moq.
Моя проблема заключается в поискеэквивалент NUnit / NSubstitute для new DefaultHttpContext()
.Подстановка HttpContext вызовет промежуточное программное обеспечение, но оно пропустит try
.Я предполагаю, что это из-за проблемы, указанной ниже.Есть ли в NUnit функция для создания реального HttpContext или я смотрю на гораздо большую инфраструктуру для достижения этой цели?
Я отправляю экземпляр DefaultHttpContext в метод Invoke.Я не могу использовать поддельный HttpContext в этом сценарии, потому что первая промежуточная программа (лямбда-функция, которую мы передали конструктору) должна будет записать в ответ.Следовательно, 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);
}
}