6af5a4f9d6
- Add GetAsync_Returns404_MapsToNotFound test - Add GetAsync_Returns400_WithValidationErrors_MapsToValidationError test - Add GetAsync_Returns401_MapsToUnauthorized test - Add GetAsync_Returns403_MapsToForbidden test - Add GetAsync_Returns500_MapsToApiError test - Add FrameworkReference to Microsoft.AspNetCore.App for ValidationProblemDetails
121 lines
3.6 KiB
C#
121 lines
3.6 KiB
C#
using System.Net;
|
|
using System.Text.Json;
|
|
using JdeScoping.Core.ApiContracts.Results;
|
|
using RichardSzalay.MockHttp;
|
|
using Shouldly;
|
|
|
|
namespace JdeScoping.Client.Tests.Services;
|
|
|
|
public class ApiClientBaseTests
|
|
{
|
|
private readonly MockHttpMessageHandler _mockHttp;
|
|
private readonly TestableApiClient _client;
|
|
|
|
public ApiClientBaseTests()
|
|
{
|
|
_mockHttp = new MockHttpMessageHandler();
|
|
var httpClient = new HttpClient(_mockHttp) { BaseAddress = new Uri("http://localhost/") };
|
|
_client = new TestableApiClient(httpClient);
|
|
}
|
|
|
|
public record TestDto(int Id, string Name);
|
|
|
|
[Fact]
|
|
public async Task GetAsync_Returns200_MapsToSuccessValue()
|
|
{
|
|
// Arrange
|
|
var expected = new TestDto(42, "Test");
|
|
_mockHttp.When("/api/test")
|
|
.Respond("application/json", JsonSerializer.Serialize(expected));
|
|
|
|
// Act
|
|
var result = await _client.GetAsync<TestDto>("/api/test");
|
|
|
|
// Assert
|
|
result.IsSuccess.ShouldBeTrue();
|
|
result.Value.Id.ShouldBe(42);
|
|
result.Value.Name.ShouldBe("Test");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAsync_Returns404_MapsToNotFound()
|
|
{
|
|
// Arrange
|
|
_mockHttp.When("/api/test")
|
|
.Respond(HttpStatusCode.NotFound);
|
|
|
|
// Act
|
|
var result = await _client.GetAsync<TestDto>("/api/test");
|
|
|
|
// Assert
|
|
result.IsNotFound.ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAsync_Returns400_WithValidationErrors_MapsToValidationError()
|
|
{
|
|
// Arrange - use actual ValidationProblemDetails structure to match production
|
|
var validationProblem = new Microsoft.AspNetCore.Mvc.ValidationProblemDetails
|
|
{
|
|
Errors =
|
|
{
|
|
["Name"] = new[] { "Name is required" },
|
|
["Id"] = new[] { "Id must be positive" }
|
|
}
|
|
};
|
|
_mockHttp.When("/api/test")
|
|
.Respond(HttpStatusCode.BadRequest, "application/json", JsonSerializer.Serialize(validationProblem, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }));
|
|
|
|
// Act
|
|
var result = await _client.GetAsync<TestDto>("/api/test");
|
|
|
|
// Assert
|
|
result.IsValidationError.ShouldBeTrue();
|
|
result.ValidationError.FieldErrors.ShouldContainKey("Name");
|
|
result.ValidationError.FieldErrors["Name"].ShouldContain("Name is required");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAsync_Returns401_MapsToUnauthorized()
|
|
{
|
|
// Arrange
|
|
_mockHttp.When("/api/test")
|
|
.Respond(HttpStatusCode.Unauthorized);
|
|
|
|
// Act
|
|
var result = await _client.GetAsync<TestDto>("/api/test");
|
|
|
|
// Assert
|
|
result.IsUnauthorized.ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAsync_Returns403_MapsToForbidden()
|
|
{
|
|
// Arrange
|
|
_mockHttp.When("/api/test")
|
|
.Respond(HttpStatusCode.Forbidden);
|
|
|
|
// Act
|
|
var result = await _client.GetAsync<TestDto>("/api/test");
|
|
|
|
// Assert
|
|
result.IsForbidden.ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAsync_Returns500_MapsToApiError()
|
|
{
|
|
// Arrange
|
|
_mockHttp.When("/api/test")
|
|
.Respond(HttpStatusCode.InternalServerError, "text/plain", "Internal Server Error");
|
|
|
|
// Act
|
|
var result = await _client.GetAsync<TestDto>("/api/test");
|
|
|
|
// Assert
|
|
result.IsError.ShouldBeTrue();
|
|
result.Error.StatusCode.ShouldBe(500);
|
|
}
|
|
}
|