Add backend test harness with mock SQLite
This commit is contained in:
18
GameList.Tests/Support/StubHttpClientFactory.cs
Normal file
18
GameList.Tests/Support/StubHttpClientFactory.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.Net.Http;
|
||||
|
||||
namespace GameList.Tests.Support;
|
||||
|
||||
internal class StubHttpClientFactory : IHttpClientFactory
|
||||
{
|
||||
private readonly StubHttpMessageHandler _handler;
|
||||
|
||||
public StubHttpClientFactory(StubHttpMessageHandler handler)
|
||||
{
|
||||
_handler = handler;
|
||||
}
|
||||
|
||||
public HttpClient CreateClient(string name)
|
||||
{
|
||||
return new HttpClient(_handler, dispose: false);
|
||||
}
|
||||
}
|
||||
35
GameList.Tests/Support/StubHttpMessageHandler.cs
Normal file
35
GameList.Tests/Support/StubHttpMessageHandler.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
namespace GameList.Tests.Support;
|
||||
|
||||
internal class StubHttpMessageHandler : HttpMessageHandler
|
||||
{
|
||||
private Func<HttpRequestMessage, HttpResponseMessage> _responder;
|
||||
|
||||
public StubHttpMessageHandler()
|
||||
{
|
||||
_responder = DefaultResponder;
|
||||
}
|
||||
|
||||
public void SetResponder(Func<HttpRequestMessage, HttpResponseMessage> responder)
|
||||
{
|
||||
_responder = responder ?? DefaultResponder;
|
||||
}
|
||||
|
||||
private static HttpResponseMessage DefaultResponder(HttpRequestMessage _)
|
||||
{
|
||||
var response = new HttpResponseMessage(HttpStatusCode.OK)
|
||||
{
|
||||
Content = new ByteArrayContent(Array.Empty<byte>())
|
||||
};
|
||||
response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
|
||||
response.Content.Headers.ContentLength = 0;
|
||||
return response;
|
||||
}
|
||||
|
||||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(_responder(request));
|
||||
}
|
||||
}
|
||||
46
GameList.Tests/Support/TestClientExtensions.cs
Normal file
46
GameList.Tests/Support/TestClientExtensions.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace GameList.Tests.Support;
|
||||
|
||||
internal static class TestClientExtensions
|
||||
{
|
||||
public static Task<HttpResponseMessage> RegisterAsync(this HttpClient client, string username, bool admin = false)
|
||||
{
|
||||
return client.PostAsJsonAsync("/api/auth/register", new
|
||||
{
|
||||
Username = username,
|
||||
Password = "Pass123!",
|
||||
DisplayName = $"{username}-name",
|
||||
AdminKey = admin ? "admin-key" : null
|
||||
});
|
||||
}
|
||||
|
||||
public static Task<HttpResponseMessage> LoginAsync(this HttpClient client, string username, string password)
|
||||
{
|
||||
return client.PostAsJsonAsync("/api/auth/login", new
|
||||
{
|
||||
Username = username,
|
||||
Password = password
|
||||
});
|
||||
}
|
||||
|
||||
public static async Task<int> CreateSuggestionAsync(this HttpClient client, string name)
|
||||
{
|
||||
var response = await client.PostAsJsonAsync("/api/suggestions", new
|
||||
{
|
||||
Name = name,
|
||||
Genre = "Coop",
|
||||
Description = (string?)null,
|
||||
ScreenshotUrl = (string?)null,
|
||||
YoutubeUrl = (string?)null,
|
||||
GameUrl = (string?)null,
|
||||
MinPlayers = (int?)null,
|
||||
MaxPlayers = (int?)null
|
||||
});
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
var json = await response.Content.ReadFromJsonAsync<JsonElement>();
|
||||
return json.GetProperty("Id").GetInt32();
|
||||
}
|
||||
}
|
||||
90
GameList.Tests/Support/TestWebApplicationFactory.cs
Normal file
90
GameList.Tests/Support/TestWebApplicationFactory.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using GameList.Data;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace GameList.Tests.Support;
|
||||
|
||||
internal class TestWebApplicationFactory : WebApplicationFactory<Program>
|
||||
{
|
||||
private SqliteConnection? _connection;
|
||||
|
||||
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
||||
{
|
||||
builder.UseEnvironment("Development");
|
||||
builder.ConfigureAppConfiguration((context, config) =>
|
||||
{
|
||||
config.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["ADMIN_PASSWORD"] = "admin-key"
|
||||
});
|
||||
});
|
||||
|
||||
builder.ConfigureServices(services =>
|
||||
{
|
||||
var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<AppDbContext>));
|
||||
if (descriptor != null)
|
||||
{
|
||||
services.Remove(descriptor);
|
||||
}
|
||||
|
||||
_connection = new SqliteConnection("Data Source=:memory:;Cache=Shared");
|
||||
_connection.Open();
|
||||
|
||||
services.AddDbContext<AppDbContext>(options =>
|
||||
{
|
||||
options.UseSqlite(_connection);
|
||||
});
|
||||
|
||||
services.AddSingleton<StubHttpMessageHandler>();
|
||||
services.AddSingleton<IHttpClientFactory, StubHttpClientFactory>();
|
||||
});
|
||||
|
||||
builder.UseSetting("https_port", "0");
|
||||
}
|
||||
|
||||
protected override IHost CreateHost(IHostBuilder builder)
|
||||
{
|
||||
var host = base.CreateHost(builder);
|
||||
|
||||
using var scope = host.Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
db.Database.EnsureCreated();
|
||||
db.Database.Migrate();
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
if (disposing)
|
||||
{
|
||||
_connection?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public StubHttpMessageHandler HttpHandler => Services.GetRequiredService<StubHttpMessageHandler>();
|
||||
|
||||
public Task WithDbContextAsync(Func<AppDbContext, Task> action)
|
||||
{
|
||||
using var scope = Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
return action(db);
|
||||
}
|
||||
|
||||
public HttpClient CreateClientWithCookies()
|
||||
{
|
||||
return CreateClient(new WebApplicationFactoryClientOptions
|
||||
{
|
||||
HandleCookies = true,
|
||||
AllowAutoRedirect = false
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user