c# XUnit Fluent Assertions:为 BadRequest 编写单元测试用例

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

我正在开发具有 CQRS 中介模式的 ASP.NET Core 8 Web API,目前正在为所有控制器创建 XUnit 测试。一切正常,预计我无法为

BadRequest
响应创建测试,因为调用控制器的客户端会抛出“错误请求”异常,而不允许我控制它。

我的测试(应该测试我试图插入重复许可证的创建):

public async Task Create400()
{
    using var scope = _lab.AppFactory.Services.CreateScope();
    var provider = scope.ServiceProvider;

    // Arrange
    var events = await _lab.InitAsync(provider, true);

    var licensesRepository = provider.GetRequiredService<IVdcQueryRepository<Licenses>>();

    var request = new CreateUpdateRequest
    {
        Name = $"New license",
        MaxCpu = 8,
        ParentId = null
    };

    // Act 
    var responseAlreadyExists = await _client.CreateBadRequest(_lab.Identity, request);

    // Assert
    // whatever
}

客户端调用控制器:

public async Task<LicenseResponse> CreateBadRequest(IdentityInfo identity, CreateUpdateRequest request, string? correlationId = null, CancellationToken ct = default)
{
    var (response, statudCode) = await ApiClient.SendAsync<LicenseResponse>(
            HttpMethod.Post,
            $"/api/license",
            message => message.AddAuthorization(identity, _options.ApiKey, correlationId),
            model: request,
            ct: ct
        );

    return response!;
}

在此客户端中:

response => My entity.
statusCode => System.Net.HttpStatusCode

控制器:

[HttpPost]
public async Task<ActionResult<LicenseResponse>> Create(
    [FromServices][IsSensitive] ICommandDispatcher dispatcher,
    [FromBody] CreateUpdateRequest request, CancellationToken ct = default)
{
    var ipAddress = HttpContext.GetIPAddress();
    var identity = HttpContext.GetIdentity();
    var httpRequest = HttpContext.Request;

    var command = new CreateCommand(identity, HttpContext.TraceIdentifier) 
    {
        CreateLicense = request,
        IpAddress = ipAddress
    };
    var result = await dispatcher.DispatchAsync(_provider, command, ct);

    return result.ToActionResult(this);
}

Mediator

CreateCommand
处理程序中的验证器:

public async ValueTask<IResponse> ValidatorAsync(CreateCommand request, RequestValidator<CreateCommand> validator, CancellationToken ct = default)
{
    var licenses = await _repository.FindAll().ToListAsync();

    var errorMsg = "There is another license with the same name. Please, choose a different one.";
    validator.RuleFor(r => r.CreateLicense.Name)
        .Must(_ => 
            { 
                return licenses.Where(x => x.Name.ToLower() == request.CreateLicense.Name.ToLower()).ToArray().Length == 0; 
            }).WithMessage(errorMsg);

    return request.OkResponse();
}

客户端对于

Create
测试工作正常,但是当我尝试为重复的名称创建测试时(例如),验证器将抛出 400,因此控制器和我的客户端(正在调用控制器),而不是让我控制 400 抛出异常并退出测试。

根据我的场景/结构,如何为 400 错误请求创建测试用例?

更新1:

当然我知道我可以使用 try / catch,捕获异常并处理它,但我不想这样做(除非没有其他选择)。我正在寻找一种优雅的方式来处理测试中的 400,事实上,是为 400 错误请求创建测试。

c# unit-testing cqrs bad-request
2个回答
0
投票

你没有说你使用什么测试框架。对于 MSTest,您可以使用 ExpectedExceptionAttribute 注释您的测试。如果它抛出这样的异常,这将使你的测试失败。

所以假设你抛出了一个(虚构的)BadRequestException:

[TestMethod]
[ExpectedException(typeof(BadRequestException))]
public async Task Create400()
{
    // ...
}

当遇到这样的异常时,此测试将成功,如果遇到另一个异常,或者根本没有异常,则失败


0
投票

我自己回答:

// Act
Func<Task> f = async () => { await WhicheverMethodThatWillThrowAnException(); };


// Assert
await f.Should().ThrowAsync<Exception>();

这样您就不必结束使用 try / catch 块来创建断言。

编辑1:找到了另一种使用XUnit的方法(就我而言,使用流畅的断言,我更喜欢我的)。

[Fact]
public void TestMethod1_Error_twoMathces()
{
    var message = "some text";
    var parser = new MessageTypeParser();
    Assert.Throws<MessageTypeParserException>(() => parser.GetType(message));
}

ExpectedException xunit .net core

© www.soinside.com 2019 - 2024. All rights reserved.