add web factory tests

This commit is contained in:
Liam Pietralla 2024-10-22 22:50:00 +11:00
parent 1cd75cf481
commit d2cf8edd87
11 changed files with 301 additions and 20 deletions

View File

@ -0,0 +1,73 @@
using Microsoft.Extensions.DependencyInjection;
using System.Net;
using System.Net.Http.Json;
using UserManager.API.IntegrationTests.Helpers;
using UserManager.Application.Features.Users.Requests;
using UserManager.Infrastructure;
namespace UserManager.API.IntegrationTests.Controllers
{
[TestClass]
public class UserControllerIntegrationTests
{
private HttpClient _client = null!;
private CustomWebApplicationFactory<Program> _factory = null!;
[TestInitialize]
public void Initialize()
{
_factory = new CustomWebApplicationFactory<Program>();
// Create a database with all migrations applied
using var scope = _factory.Services.CreateScope();
var services = scope.ServiceProvider;
var context = services.GetRequiredService<UserManagerContext>();
context.Database.EnsureCreated();
_client = _factory.CreateClient();
}
[TestCleanup]
public void Cleanup()
{
_client.Dispose();
_factory.Dispose();
}
[TestMethod]
public async Task CreateUserAsync_Returns400WithValidation_ForInvalidRequest()
{
// Arrange
var request = new CreateUserRequestDto
{
FirstName = "",
LastName = "",
};
// Act
var response = await _client.PostAsJsonAsync("/api/user", request);
// Assert
Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);
Assert.AreEqual("{\"FirstName\":[\"FirstName is required.\"],\"LastName\":[\"LastName is required.\"]}", response.Content.ReadAsStringAsync().Result);
}
[TestMethod]
public async Task CreateUserAsync_Returns200OK_ForValidRequest()
{
// Arrange
var request = new CreateUserRequestDto
{
FirstName = "James",
LastName = "Smith",
};
// Act
var response = await _client.PostAsJsonAsync("/api/user", request);
// Assert
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
}
}

View File

@ -0,0 +1,47 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System.Data.Common;
using UserManager.Infrastructure;
namespace UserManager.API.IntegrationTests.Helpers
{
public class CustomWebApplicationFactory<TProgram> : WebApplicationFactory<TProgram> where TProgram : class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
// Override the configure services method to add a test context
builder.ConfigureServices(services =>
{
var dbContextDescriptor = services.SingleOrDefault(
d => d.ServiceType ==
typeof(DbContextOptions<UserManagerContext>));
services.Remove(dbContextDescriptor!);
var dbConnectionDescriptor = services.SingleOrDefault(
d => d.ServiceType ==
typeof(DbConnection));
services.Remove(dbConnectionDescriptor!);
// Create open SqliteConnection so EF won't automatically close it.
services.AddSingleton<DbConnection>(container =>
{
var connection = new SqliteConnection("DataSource=:memory:");
connection.Open();
return connection;
});
services.AddDbContext<UserManagerContext>((container, options) =>
{
var connection = container.GetRequiredService<DbConnection>();
options.UseSqlite(connection);
});
});
}
}
}

View File

@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<PreserveCompilationContext>true</PreserveCompilationContext>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.10" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="8.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.10" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\UserManager.API\UserManager.API.csproj" />
<ProjectReference Include="..\UserManager.Infrastructure\UserManager.Infrastructure.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
</Project>

View File

@ -27,7 +27,7 @@ namespace UserManager.API.Controllers
if (!validationResult.IsValid) if (!validationResult.IsValid)
{ {
return BadRequest(validationResult.Errors); return BadRequest(validationResult.ToDictionary());
} }
else else
{ {

View File

@ -28,3 +28,5 @@ app.UseAuthorization();
app.MapControllers(); app.MapControllers();
app.Run(); app.Run();
public partial class Program { }

View File

@ -0,0 +1,63 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using UserManager.Infrastructure;
#nullable disable
namespace UserManager.Infrastructure.Migrations
{
[DbContext(typeof(UserManagerContext))]
[Migration("20241022112315_BaseColumns")]
partial class BaseColumns
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.10")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("UserManager.Domain.Entities.User", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("UserId"));
b.Property<DateTime>("CreateAtUtc")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("DeletedAtUtc")
.HasColumnType("timestamp with time zone");
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime?>("UpdatedAtUtc")
.HasColumnType("timestamp with time zone");
b.HasKey("UserId");
b.ToTable("Users");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,61 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace UserManager.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class BaseColumns : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "CreateAtUtc",
table: "Users",
type: "timestamp with time zone",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
migrationBuilder.AddColumn<DateTime>(
name: "DeletedAtUtc",
table: "Users",
type: "timestamp with time zone",
nullable: true);
migrationBuilder.AddColumn<bool>(
name: "IsDeleted",
table: "Users",
type: "boolean",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<DateTime>(
name: "UpdatedAtUtc",
table: "Users",
type: "timestamp with time zone",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "CreateAtUtc",
table: "Users");
migrationBuilder.DropColumn(
name: "DeletedAtUtc",
table: "Users");
migrationBuilder.DropColumn(
name: "IsDeleted",
table: "Users");
migrationBuilder.DropColumn(
name: "UpdatedAtUtc",
table: "Users");
}
}
}

View File

@ -1,4 +1,5 @@
// <auto-generated /> // <auto-generated />
using System;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
@ -29,14 +30,26 @@ namespace UserManager.Infrastructure.Migrations
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("UserId")); NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("UserId"));
b.Property<DateTime>("CreateAtUtc")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("DeletedAtUtc")
.HasColumnType("timestamp with time zone");
b.Property<string>("FirstName") b.Property<string>("FirstName")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("LastName") b.Property<string>("LastName")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<DateTime?>("UpdatedAtUtc")
.HasColumnType("timestamp with time zone");
b.HasKey("UserId"); b.HasKey("UserId");
b.ToTable("Users"); b.ToTable("Users");

View File

@ -17,7 +17,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UserManager.Application", "
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UserManager.Application.UnitTests", "..\tests\UserManager.Application.Tests\UserManager.Application.UnitTests.csproj", "{B0F63D11-6933-4D87-B0D8-6DD7DFC5A23C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UserManager.Application.UnitTests", "..\tests\UserManager.Application.Tests\UserManager.Application.UnitTests.csproj", "{B0F63D11-6933-4D87-B0D8-6DD7DFC5A23C}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserManager.Application.IntegrationTests", "..\tests\UserManager.Application.IntegrationTests\UserManager.Application.IntegrationTests.csproj", "{2EDF27EB-CC43-4F38-86A5-BDC1D6974BA5}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UserManager.Application.IntegrationTests", "..\tests\UserManager.Application.IntegrationTests\UserManager.Application.IntegrationTests.csproj", "{2EDF27EB-CC43-4F38-86A5-BDC1D6974BA5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserManager.API.IntegrationTests", "UserManager.API.IntegrationTests\UserManager.API.IntegrationTests.csproj", "{FB1D2DF8-F06A-4414-B855-267BCD76B865}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -49,6 +51,10 @@ Global
{2EDF27EB-CC43-4F38-86A5-BDC1D6974BA5}.Debug|Any CPU.Build.0 = Debug|Any CPU {2EDF27EB-CC43-4F38-86A5-BDC1D6974BA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2EDF27EB-CC43-4F38-86A5-BDC1D6974BA5}.Release|Any CPU.ActiveCfg = Release|Any CPU {2EDF27EB-CC43-4F38-86A5-BDC1D6974BA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2EDF27EB-CC43-4F38-86A5-BDC1D6974BA5}.Release|Any CPU.Build.0 = Release|Any CPU {2EDF27EB-CC43-4F38-86A5-BDC1D6974BA5}.Release|Any CPU.Build.0 = Release|Any CPU
{FB1D2DF8-F06A-4414-B855-267BCD76B865}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FB1D2DF8-F06A-4414-B855-267BCD76B865}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FB1D2DF8-F06A-4414-B855-267BCD76B865}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FB1D2DF8-F06A-4414-B855-267BCD76B865}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -60,6 +66,7 @@ Global
{C7215859-A216-4527-A192-7B8F57E50BB4} = {74E412ED-9D1B-4597-BBFD-05623C814F98} {C7215859-A216-4527-A192-7B8F57E50BB4} = {74E412ED-9D1B-4597-BBFD-05623C814F98}
{B0F63D11-6933-4D87-B0D8-6DD7DFC5A23C} = {5B673FE8-32DA-4CD3-8394-1BD8E1275270} {B0F63D11-6933-4D87-B0D8-6DD7DFC5A23C} = {5B673FE8-32DA-4CD3-8394-1BD8E1275270}
{2EDF27EB-CC43-4F38-86A5-BDC1D6974BA5} = {5B673FE8-32DA-4CD3-8394-1BD8E1275270} {2EDF27EB-CC43-4F38-86A5-BDC1D6974BA5} = {5B673FE8-32DA-4CD3-8394-1BD8E1275270}
{FB1D2DF8-F06A-4414-B855-267BCD76B865} = {5B673FE8-32DA-4CD3-8394-1BD8E1275270}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6E7F90F4-4A09-4CDB-8653-6E094E164853} SolutionGuid = {6E7F90F4-4A09-4CDB-8653-6E094E164853}

View File

@ -1,11 +0,0 @@
namespace UserManager.Application.IntegrationTests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
}
}
}

View File

@ -1,7 +0,0 @@
namespace UserManager.Application.Tests
{
public class Class1
{
}
}