Skip to content

Instantly share code, notes, and snippets.

@dukesteen
Created November 28, 2022 17:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dukesteen/e21a79071222f989e5b880d3eb256809 to your computer and use it in GitHub Desktop.
Save dukesteen/e21a79071222f989e5b880d3eb256809 to your computer and use it in GitHub Desktop.
{
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:5000"
}
}
},
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": {
"Default": "Verbose",
"Override": {
"Microsoft": "Information",
"Microsoft.EntityFrameworkCore.Database.Command": "Warning",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.Mvc.*": "Information",
"Microsoft.AspNetCore.Routing.*": "Warning",
"Microsoft.AspNetCore.Hosting.Diagnostics": "Warning"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] [{SourceContext}] {Message:lj}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext" ]
},
"ConnectionStrings": {
"DefaultConnection": "User ID=postgres;Password=root;Server=localhost;Port=5436;Database=timespace;Include Error Detail=true;"
}
}
namespace Timespace.IntegrationTests;
using static Testing;
[TestFixture]
public abstract class BaseTestFixture
{
[SetUp]
public async Task TestSetUp()
{
await ResetState();
}
}
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Timespace.Api.Infrastructure.Persistence;
namespace Timespace.IntegrationTests;
internal class CustomWebApplicationFactory : WebApplicationFactory<Program>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureAppConfiguration(configurationBuilder =>
{
var integrationConfig = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables()
.Build();
configurationBuilder.AddConfiguration(integrationConfig);
});
builder.ConfigureServices((webHostBuilderContext, services) =>
{
services
.Remove<DbContextOptions<AppDbContext>>()
.AddDbContext<AppDbContext>((sp, options) =>
options.UseNpgsql(webHostBuilderContext.Configuration.GetConnectionString("DefaultConnection"),
npgsqlDbContextOptionsBuilder =>
{
npgsqlDbContextOptionsBuilder.MigrationsAssembly(typeof(AppDbContext).Assembly.FullName);
npgsqlDbContextOptionsBuilder.UseNodaTime();
}));
});
}
}
global using NUnit.Framework;
using Microsoft.Extensions.DependencyInjection;
namespace Timespace.IntegrationTests;
public static class ServiceCollectionExtensions
{
public static IServiceCollection Remove<TService>(this IServiceCollection services)
{
var serviceDescriptor = services.FirstOrDefault(d =>
d.ServiceType == typeof(TService));
if (serviceDescriptor != null)
{
services.Remove(serviceDescriptor);
}
return services;
}
}
using FluentAssertions;
using Timespace.Api.Application.Features.Authentication.Registration.Commands;
namespace Timespace.IntegrationTests.Features.Authentication.Registration;
using static Testing;
public class Test : BaseTestFixture
{
[Test]
public async Task ShouldReturnString()
{
var command = new TestCommand.Command("test string");
var result = await SendAsync(command);
result.SomeString.Should().Be("test string");
}
}
using MediatR;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Respawn;
using Respawn.Graph;
using Timespace.Api.Infrastructure.Persistence;
namespace Timespace.IntegrationTests;
[SetUpFixture]
public partial class Testing
{
private static WebApplicationFactory<Program> _factory = null!;
private static IConfiguration _configuration = null!;
private static IServiceScopeFactory _scopeFactory = null!;
private static Respawner _respawner = null!;
[OneTimeSetUp]
public async Task RunBeforeAnyTests()
{
_factory = new CustomWebApplicationFactory();
_scopeFactory = _factory.Services.GetRequiredService<IServiceScopeFactory>();
_configuration = _factory.Services.GetRequiredService<IConfiguration>();
using var scope = _scopeFactory.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
await dbContext.Database.EnsureCreatedAsync();
await dbContext.Database.MigrateAsync();
_respawner = await Respawner.CreateAsync(_configuration.GetConnectionString("DefaultConnection")!, new RespawnerOptions()
{
TablesToIgnore = new Table[] { "__EFMigrationsHistory" }
});
}
public static async Task<TResponse> SendAsync<TResponse>(IRequest<TResponse> request)
{
using var scope = _scopeFactory.CreateScope();
var mediator = scope.ServiceProvider.GetRequiredService<ISender>();
return await mediator.Send(request);
}
public static async Task ResetState()
{
await _respawner.ResetAsync(_configuration.GetConnectionString("DefaultConnection")!);
}
public static async Task<TEntity?> FindAsync<TEntity>(params object[] keyValues)
where TEntity : class
{
using var scope = _scopeFactory.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
return await context.FindAsync<TEntity>(keyValues);
}
public static async Task AddAsync<TEntity>(TEntity entity)
where TEntity : class
{
using var scope = _scopeFactory.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
context.Add(entity);
await context.SaveChangesAsync();
}
public static async Task<int> CountAsync<TEntity>() where TEntity : class
{
using var scope = _scopeFactory.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
return await context.Set<TEntity>().CountAsync();
}
[OneTimeTearDown]
public void RunAfterAnyTests()
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment