From 517c42250ddcf3f6423a8ba380f7e4e69fd75392 Mon Sep 17 00:00:00 2001 From: cesnimda Date: Wed, 1 Apr 2026 10:48:28 +0200 Subject: [PATCH] Refactor repeated test host setup --- .../AuthAndSystemControllerTests.cs | 15 +----- JobTrackerApi.Tests/BackupControllerTests.cs | 10 +--- JobTrackerApi.Tests/GmailControllerTests.cs | 8 +-- .../JobApplicationsApplicationPackageTests.cs | 23 ++------- .../JobApplicationsEndpointBehaviorTests.cs | 20 ++------ .../JobApplicationsFollowUpDraftTests.cs | 23 ++------- .../JobApplicationsMariaDraftTests.cs | 20 ++------ .../JobApplicationsWorkflowSignalsTests.cs | 22 ++------ .../ProfileCvControllerTests.cs | 23 ++------- .../TestSupport/TestHostFactory.cs | 50 +++++++++++++++++++ 10 files changed, 74 insertions(+), 140 deletions(-) create mode 100644 JobTrackerApi.Tests/TestSupport/TestHostFactory.cs diff --git a/JobTrackerApi.Tests/AuthAndSystemControllerTests.cs b/JobTrackerApi.Tests/AuthAndSystemControllerTests.cs index 08667e2..265243c 100644 --- a/JobTrackerApi.Tests/AuthAndSystemControllerTests.cs +++ b/JobTrackerApi.Tests/AuthAndSystemControllerTests.cs @@ -1,13 +1,13 @@ using JobTrackerApi.Controllers; using JobTrackerApi.Models; using JobTrackerApi.Services; +using JobTrackerApi.Tests.TestSupport; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore.Query; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; using Moq; using System.Collections; using System.Linq.Expressions; @@ -162,18 +162,7 @@ public sealed class AuthAndSystemControllerTests private static Mock> CreateUserManager() { - var store = new Mock>(); - return new Mock>( - store.Object, - Options.Create(new IdentityOptions()), - new PasswordHasher(), - Array.Empty>(), - Array.Empty>(), - new UpperInvariantLookupNormalizer(), - new IdentityErrorDescriber(), - null!, - new NullLogger>() - ); + return TestHostFactory.CreateUserManager(); } private sealed class TestAsyncQueryProvider : IAsyncQueryProvider diff --git a/JobTrackerApi.Tests/BackupControllerTests.cs b/JobTrackerApi.Tests/BackupControllerTests.cs index 0a2f3e8..1223b7d 100644 --- a/JobTrackerApi.Tests/BackupControllerTests.cs +++ b/JobTrackerApi.Tests/BackupControllerTests.cs @@ -2,11 +2,10 @@ using JobTrackerApi.Controllers; using JobTrackerApi.Data; using JobTrackerApi.Models; using JobTrackerApi.Services; +using JobTrackerApi.Tests.TestSupport; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging.Abstractions; -using Moq; using Xunit; namespace JobTrackerApi.Tests; @@ -34,11 +33,6 @@ public sealed class BackupControllerTests private static JobTrackerContext CreateDb() { - var options = new DbContextOptionsBuilder() - .UseInMemoryDatabase(Guid.NewGuid().ToString()) - .Options; - var currentUser = new Mock(); - currentUser.SetupGet(x => x.UserId).Returns("user-1"); - return new JobTrackerContext(options, currentUser.Object); + return TestHostFactory.CreateInMemoryDb(); } } diff --git a/JobTrackerApi.Tests/GmailControllerTests.cs b/JobTrackerApi.Tests/GmailControllerTests.cs index 1576107..bfde776 100644 --- a/JobTrackerApi.Tests/GmailControllerTests.cs +++ b/JobTrackerApi.Tests/GmailControllerTests.cs @@ -3,6 +3,7 @@ using JobTrackerApi.Controllers; using JobTrackerApi.Data; using JobTrackerApi.Models; using JobTrackerApi.Services; +using JobTrackerApi.Tests.TestSupport; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -520,12 +521,7 @@ public sealed class GmailControllerTests private static JobTrackerContext CreateDb() { - var options = new DbContextOptionsBuilder() - .UseInMemoryDatabase(Guid.NewGuid().ToString()) - .Options; - var currentUser = new Mock(); - currentUser.SetupGet(service => service.UserId).Returns("user-1"); - return new JobTrackerContext(options, currentUser.Object); + return TestHostFactory.CreateInMemoryDb(); } private static Microsoft.Extensions.Configuration.IConfiguration BuildConfig() diff --git a/JobTrackerApi.Tests/JobApplicationsApplicationPackageTests.cs b/JobTrackerApi.Tests/JobApplicationsApplicationPackageTests.cs index 1ce6feb..c684925 100644 --- a/JobTrackerApi.Tests/JobApplicationsApplicationPackageTests.cs +++ b/JobTrackerApi.Tests/JobApplicationsApplicationPackageTests.cs @@ -3,12 +3,12 @@ using JobTrackerApi.Controllers; using JobTrackerApi.Data; using JobTrackerApi.Models; using JobTrackerApi.Services; +using JobTrackerApi.Tests.TestSupport; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; using Moq; using Xunit; @@ -475,29 +475,12 @@ public sealed class JobApplicationsApplicationPackageTests private static JobTrackerContext CreateDb() { - var options = new DbContextOptionsBuilder() - .UseInMemoryDatabase(Guid.NewGuid().ToString()) - .Options; - var currentUser = new Mock(); - currentUser.SetupGet(service => service.UserId).Returns("user-1"); - return new JobTrackerContext(options, currentUser.Object); + return TestHostFactory.CreateInMemoryDb(); } private static Mock> CreateUserManager(ApplicationUser? user = null) { - var store = new Mock>(); - var manager = new Mock>( - store.Object, - Options.Create(new IdentityOptions()), - new PasswordHasher(), - Array.Empty>(), - Array.Empty>(), - new UpperInvariantLookupNormalizer(), - new IdentityErrorDescriber(), - null!, - new NullLogger>()); - manager.Setup(x => x.FindByIdAsync(It.IsAny())).ReturnsAsync((string id) => user is not null && user.Id == id ? user : null); - return manager; + return TestHostFactory.CreateUserManager(user); } private sealed class TestCvTemplateRenderer : ICvTemplateRenderer diff --git a/JobTrackerApi.Tests/JobApplicationsEndpointBehaviorTests.cs b/JobTrackerApi.Tests/JobApplicationsEndpointBehaviorTests.cs index ea5447d..fee8f7b 100644 --- a/JobTrackerApi.Tests/JobApplicationsEndpointBehaviorTests.cs +++ b/JobTrackerApi.Tests/JobApplicationsEndpointBehaviorTests.cs @@ -3,6 +3,7 @@ using JobTrackerApi.Controllers; using JobTrackerApi.Data; using JobTrackerApi.Models; using JobTrackerApi.Services; +using JobTrackerApi.Tests.TestSupport; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -77,26 +78,11 @@ public sealed class JobApplicationsEndpointBehaviorTests private static Mock> CreateUserManager() { - var store = new Mock>(); - return new Mock>( - store.Object, - null!, - null!, - null!, - null!, - null!, - null!, - null!, - null!); + return TestHostFactory.CreateUserManager(); } private static JobTrackerContext CreateDb() { - var options = new DbContextOptionsBuilder() - .UseInMemoryDatabase(Guid.NewGuid().ToString()) - .Options; - var currentUser = new Mock(); - currentUser.SetupGet(x => x.UserId).Returns("user-1"); - return new JobTrackerContext(options, currentUser.Object); + return TestHostFactory.CreateInMemoryDb(); } } diff --git a/JobTrackerApi.Tests/JobApplicationsFollowUpDraftTests.cs b/JobTrackerApi.Tests/JobApplicationsFollowUpDraftTests.cs index fafc75a..01b6cb3 100644 --- a/JobTrackerApi.Tests/JobApplicationsFollowUpDraftTests.cs +++ b/JobTrackerApi.Tests/JobApplicationsFollowUpDraftTests.cs @@ -3,12 +3,11 @@ using JobTrackerApi.Controllers; using JobTrackerApi.Data; using JobTrackerApi.Models; using JobTrackerApi.Services; +using JobTrackerApi.Tests.TestSupport; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; using Moq; using Xunit; @@ -122,27 +121,11 @@ public sealed class JobApplicationsFollowUpDraftTests private static JobTrackerContext CreateDb() { - var options = new DbContextOptionsBuilder() - .UseInMemoryDatabase(Guid.NewGuid().ToString()) - .Options; - var currentUser = new Mock(); - currentUser.SetupGet(service => service.UserId).Returns("user-1"); - return new JobTrackerContext(options, currentUser.Object); + return TestHostFactory.CreateInMemoryDb(); } private static Mock> CreateUserManager() { - var store = new Mock>(); - return new Mock>( - store.Object, - Options.Create(new IdentityOptions()), - new PasswordHasher(), - Array.Empty>(), - Array.Empty>(), - new UpperInvariantLookupNormalizer(), - new IdentityErrorDescriber(), - null!, - new NullLogger>() - ); + return TestHostFactory.CreateUserManager(); } } diff --git a/JobTrackerApi.Tests/JobApplicationsMariaDraftTests.cs b/JobTrackerApi.Tests/JobApplicationsMariaDraftTests.cs index 6b5ba0a..cf7b58c 100644 --- a/JobTrackerApi.Tests/JobApplicationsMariaDraftTests.cs +++ b/JobTrackerApi.Tests/JobApplicationsMariaDraftTests.cs @@ -3,6 +3,7 @@ using JobTrackerApi.Controllers; using JobTrackerApi.Data; using JobTrackerApi.Models; using JobTrackerApi.Services; +using JobTrackerApi.Tests.TestSupport; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -53,26 +54,11 @@ public sealed class JobApplicationsMariaDraftTests private static Mock> CreateUserManager() { - var store = new Mock>(); - return new Mock>( - store.Object, - null!, - null!, - null!, - null!, - null!, - null!, - null!, - null!); + return TestHostFactory.CreateUserManager(); } private static JobTrackerContext CreateDb() { - var options = new DbContextOptionsBuilder() - .UseInMemoryDatabase(Guid.NewGuid().ToString()) - .Options; - var currentUser = new Mock(); - currentUser.SetupGet(x => x.UserId).Returns("user-1"); - return new JobTrackerContext(options, currentUser.Object); + return TestHostFactory.CreateInMemoryDb(); } } diff --git a/JobTrackerApi.Tests/JobApplicationsWorkflowSignalsTests.cs b/JobTrackerApi.Tests/JobApplicationsWorkflowSignalsTests.cs index 732ba93..126d569 100644 --- a/JobTrackerApi.Tests/JobApplicationsWorkflowSignalsTests.cs +++ b/JobTrackerApi.Tests/JobApplicationsWorkflowSignalsTests.cs @@ -3,12 +3,12 @@ using JobTrackerApi.Controllers; using JobTrackerApi.Data; using JobTrackerApi.Models; using JobTrackerApi.Services; +using JobTrackerApi.Tests.TestSupport; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; using Moq; using Xunit; @@ -126,27 +126,11 @@ public sealed class JobApplicationsWorkflowSignalsTests private static JobTrackerContext CreateDb() { - var options = new DbContextOptionsBuilder() - .UseInMemoryDatabase(Guid.NewGuid().ToString()) - .Options; - var currentUser = new Mock(); - currentUser.SetupGet(service => service.UserId).Returns("user-1"); - return new JobTrackerContext(options, currentUser.Object); + return TestHostFactory.CreateInMemoryDb(); } private static Mock> CreateUserManager() { - var store = new Mock>(); - return new Mock>( - store.Object, - Options.Create(new IdentityOptions()), - new PasswordHasher(), - Array.Empty>(), - Array.Empty>(), - new UpperInvariantLookupNormalizer(), - new IdentityErrorDescriber(), - null!, - new NullLogger>() - ); + return TestHostFactory.CreateUserManager(); } } diff --git a/JobTrackerApi.Tests/ProfileCvControllerTests.cs b/JobTrackerApi.Tests/ProfileCvControllerTests.cs index ff9cf1e..34f62c4 100644 --- a/JobTrackerApi.Tests/ProfileCvControllerTests.cs +++ b/JobTrackerApi.Tests/ProfileCvControllerTests.cs @@ -5,14 +5,13 @@ using JobTrackerApi.Controllers; using JobTrackerApi.Data; using JobTrackerApi.Models; using JobTrackerApi.Services; +using JobTrackerApi.Tests.TestSupport; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; using Moq; using Xunit; @@ -708,12 +707,7 @@ public sealed class ProfileCvControllerTests private static JobTrackerContext CreateDb(string userId = "user-1") { - var options = new DbContextOptionsBuilder() - .UseInMemoryDatabase(Guid.NewGuid().ToString()) - .Options; - var currentUser = new Mock(); - currentUser.SetupGet(x => x.UserId).Returns(userId); - return new JobTrackerContext(options, currentUser.Object); + return TestHostFactory.CreateInMemoryDb(userId); } private static AppPaths CreatePaths() @@ -736,17 +730,6 @@ public sealed class ProfileCvControllerTests private static Mock> CreateUserManager() { - var store = new Mock>(); - return new Mock>( - store.Object, - Options.Create(new IdentityOptions()), - new PasswordHasher(), - Array.Empty>(), - Array.Empty>(), - new UpperInvariantLookupNormalizer(), - new IdentityErrorDescriber(), - null!, - new NullLogger>() - ); + return TestHostFactory.CreateUserManager(); } } diff --git a/JobTrackerApi.Tests/TestSupport/TestHostFactory.cs b/JobTrackerApi.Tests/TestSupport/TestHostFactory.cs new file mode 100644 index 0000000..26f9acd --- /dev/null +++ b/JobTrackerApi.Tests/TestSupport/TestHostFactory.cs @@ -0,0 +1,50 @@ +using JobTrackerApi.Data; +using JobTrackerApi.Models; +using JobTrackerApi.Services; +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Moq; + +namespace JobTrackerApi.Tests.TestSupport; + +public static class TestHostFactory +{ + // Keep the EF-backed controller tests on the same minimal setup so they fail for product + // reasons, not because each file drifted into a slightly different fake host configuration. + public static JobTrackerContext CreateInMemoryDb(string userId = "user-1") + { + var options = new DbContextOptionsBuilder() + .UseInMemoryDatabase(Guid.NewGuid().ToString()) + .Options; + var currentUser = new Mock(); + currentUser.SetupGet(service => service.UserId).Returns(userId); + return new JobTrackerContext(options, currentUser.Object); + } + + public static Mock> CreateUserManager(ApplicationUser? lookupUser = null) + { + var store = new Mock>(); + var manager = new Mock>( + store.Object, + Options.Create(new IdentityOptions()), + new PasswordHasher(), + Array.Empty>(), + Array.Empty>(), + new UpperInvariantLookupNormalizer(), + new IdentityErrorDescriber(), + null!, + new NullLogger>() + ); + + if (lookupUser is not null) + { + manager + .Setup(x => x.FindByIdAsync(It.IsAny())) + .ReturnsAsync((string id) => lookupUser.Id == id ? lookupUser : null); + } + + return manager; + } +}