使用 NUnit 和 NSubstitute 进行单元测试中间件

问题描述 投票:0回答:1

我在 ASP.NET Core 站点中编写了一些中间件,我正在尝试对其进行单元测试,主要是遵循使用 Moqthis 指南

我的问题是找到

new DefaultHttpContext()
的 NUnit/NSubstitute 等效项。替换 HttpContext 将触发中间件,但它会传递
try
。我认为这是因为下面引用的问题。 NUnit 是否具有创建真正的 HttpContext 的功能,或者我是否正在寻找更多基础设施来实现此目的?

我将 DefaultHttpContext 的实例发送到 Invoke 方法。在这种情况下,我无法使用模拟的 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);
    }
}
unit-testing asp.net-core nunit middleware nsubstitute
1个回答
0
投票

DefaultHttpContext
只是
HttpContext
抽象类的默认实现。

你可以做

var HttpContextSub = Substitute.For<HttpContext>();
© www.soinside.com 2019 - 2024. All rights reserved.