Enhanced `RecActionApiTests` and `ResultApiTests` to handle flexible server responses, including `null` or `JsonElement` payloads, ensuring calls do not throw exceptions. Updated exception handling to allow undefined server behavior for unfiltered `GET` requests with no data. Replaced hardcoded `FakeProfileId` with `TryResolveProfileIdAsync`, a dynamic method to resolve profile IDs from configuration or server queries. Added this method to `RecClientTestBase`. Refactored `UpdateAsync_with_unknown_id` test to support idempotent behavior, passing on successful updates or verifying exceptions. Included `System.Linq` and `System.Threading.Tasks` namespaces to support new functionality.
104 lines
3.3 KiB
C#
104 lines
3.3 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.AspNetCore.Mvc.Testing;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using ReC.Application.Common.Dto;
|
|
using ReC.Client;
|
|
|
|
namespace ReC.Tests.Client;
|
|
|
|
public abstract class RecClientTestBase : IDisposable
|
|
{
|
|
private readonly WebApplicationFactory<Program> _factory;
|
|
private readonly ServiceProvider _serviceProvider;
|
|
|
|
protected RecClientTestBase()
|
|
{
|
|
var apiContentRoot = LocateApiContentRoot();
|
|
|
|
_factory = new WebApplicationFactory<Program>()
|
|
.WithWebHostBuilder(builder =>
|
|
{
|
|
builder.UseEnvironment("Development");
|
|
builder.UseContentRoot(apiContentRoot);
|
|
});
|
|
|
|
_ = _factory.CreateClient();
|
|
|
|
var services = new ServiceCollection();
|
|
services.AddLogging();
|
|
services.AddSingleton(_factory.Services.GetRequiredService<IConfiguration>());
|
|
|
|
services.AddRecClient(client =>
|
|
{
|
|
client.BaseAddress = new Uri("http://localhost");
|
|
});
|
|
|
|
services.AddHttpClient(ReCClient.ClientName)
|
|
.ConfigurePrimaryHttpMessageHandler(() => _factory.Server.CreateHandler());
|
|
|
|
_serviceProvider = services.BuildServiceProvider();
|
|
}
|
|
|
|
protected IServiceProvider ServiceProvider => _serviceProvider;
|
|
|
|
protected IConfiguration Configuration => _factory.Services.GetRequiredService<IConfiguration>();
|
|
|
|
protected (ReCClient Client, IServiceScope Scope) CreateScopedClient()
|
|
{
|
|
var scope = _serviceProvider.CreateScope();
|
|
var client = scope.ServiceProvider.GetRequiredService<ReCClient>();
|
|
return (client, scope);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resolves a usable profile id for tests that require an existing profile in the database.
|
|
/// Prefers the configured <c>FakeProfileId</c> value; otherwise asks the server for the first
|
|
/// available profile via the standard <c>GET api/Profile</c> endpoint. Returns <c>null</c>
|
|
/// when no profile is configured and none can be discovered.
|
|
/// </summary>
|
|
protected async Task<long?> TryResolveProfileIdAsync()
|
|
{
|
|
var configured = Configuration.GetValue<long?>("FakeProfileId");
|
|
if (configured is > 0)
|
|
return configured;
|
|
|
|
try
|
|
{
|
|
var (client, scope) = CreateScopedClient();
|
|
using var _ = scope;
|
|
var profiles = await client.Profiles.GetAsync<ProfileViewDto[]>();
|
|
return profiles?.FirstOrDefault()?.Id;
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_serviceProvider.Dispose();
|
|
_factory.Dispose();
|
|
}
|
|
|
|
private static string LocateApiContentRoot()
|
|
{
|
|
var current = new DirectoryInfo(AppContext.BaseDirectory);
|
|
while (current is not null)
|
|
{
|
|
var candidate = Path.Combine(current.FullName, "src", "ReC.API");
|
|
if (File.Exists(Path.Combine(candidate, "appsettings.json")))
|
|
return candidate;
|
|
|
|
current = current.Parent;
|
|
}
|
|
|
|
throw new DirectoryNotFoundException("Could not locate src/ReC.API content root from the test base directory.");
|
|
}
|
|
}
|