Reputation: 2862
I'm working on an ASP.NET Core 8 Web API with CQRS mediator pattern and I'm currently creating XUnit tests for all the controllers. Everything's working fine, expect I cannot create tests for BadRequest
responses, as the client which calls the controller throws a "Bad Request" exception without allowing me to control it.
My test (which is supposed to test a create where I'm trying to insert a duplicated license):
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
}
The client to call controller:
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!;
}
In this client:
response => My entity.
statusCode => System.Net.HttpStatusCode
The controller:
[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);
}
The validator in the Mediator CreateCommand
handler:
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();
}
The client is working fine for a Create
test, but when I try to create a test for a duplicated name (for example), the validator will throw a 400, and so the controller, and my client (which is calling the controller) instead of allowing me to control that 400 is throwing an exception and exiting the test.
How do I create a test case for a 400 Bad Request given my scenario / structure?
Update 1:
Of course I know I could use a try / catch, catch the exception and treat it, but I'd prefer not to do so (unless there is no other choice). I'm looking for an elegant way to handle a 400 in a test, in fact, to create a test for a 400 Bad Request.
Upvotes: 2
Views: 231
Reputation: 2862
I'll answer myself:
// Act
Func<Task> f = async () => { await WhicheverMethodThatWillThrowAnException(); };
// Assert
await f.Should().ThrowAsync<Exception>();
This way you don't have to end using a try / catch block to create the asserts.
Edit 1: Found another way to go for XUnit (in my case, working with fluent assertions, I prefer mine).
[Fact]
public void TestMethod1_Error_twoMathces()
{
var message = "some text";
var parser = new MessageTypeParser();
Assert.Throws<MessageTypeParserException>(() => parser.GetType(message));
}
ExpectedException xunit .net core
Upvotes: 1
Reputation: 77354
You did not say what test framework you use. For MSTest, you could annotate your test with an ExpectedExceptionAttribute. This will fail your test, if it does not throw such an exception.
So assuming you get a (fictional) BadRequestException thrown:
[TestMethod]
[ExpectedException(typeof(BadRequestException))]
public async Task Create400()
{
// ...
}
this test will succeed when it gets such an exception, and fail if it gets another exception, or no exception at all.
Upvotes: 0