我正在开发具有 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 错误请求创建测试。
你没有说你使用什么测试框架。对于 MSTest,您可以使用 ExpectedExceptionAttribute 注释您的测试。如果它不抛出这样的异常,这将使你的测试失败。
所以假设你抛出了一个(虚构的)BadRequestException:
[TestMethod]
[ExpectedException(typeof(BadRequestException))]
public async Task Create400()
{
// ...
}
当遇到这样的异常时,此测试将成功,如果遇到另一个异常,或者根本没有异常,则失败。
我自己回答:
// 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));
}