diff --git a/tests/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/tests/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs index bd9418bdb6..45fb305de9 100644 --- a/tests/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs +++ b/tests/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs @@ -12,13 +12,16 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Moq; using NUnit.Framework; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Tests.Common.Testing; using Umbraco.Cms.Tests.Integration.DependencyInjection; @@ -77,28 +80,55 @@ namespace Umbraco.Cms.Tests.Integration.TestServerTest LinkGenerator = Factory.Services.GetRequiredService(); } - public override IHostBuilder CreateHostBuilder() + protected override IHostBuilder CreateHostBuilder() { - IHostBuilder builder = base.CreateHostBuilder(); - builder.ConfigureWebHost(builder => - { - // need to configure the IWebHostEnvironment too - builder.ConfigureServices((c, s) => c.HostingEnvironment = TestHelper.GetWebHostEnvironment()); + /* It is important that ConfigureWebHost is called before ConfigureServices, this is consistent with the host setup + * found in Program.cs and avoids nasty surprises. + * + * e.g. the registration for RefreshingRazorViewEngine requires that IWebHostEnvironment is registered + * at the point in time that the service collection is snapshotted. + */ + IHostBuilder hostBuilder = Host.CreateDefaultBuilder() + .ConfigureAppConfiguration((context, configBuilder) => + { + context.HostingEnvironment = TestHelper.GetWebHostEnvironment(); + configBuilder.Sources.Clear(); + configBuilder.AddInMemoryCollection(InMemoryConfiguration); - // call startup - builder.Configure(app => Configure(app)); - }) - .UseDefaultServiceProvider(cfg => - { - // These default to true *if* WebHostEnvironment.EnvironmentName == Development - // When running tests, EnvironmentName used to be null on the mock that we register into services. - // Enable opt in for tests so that validation occurs regardless of environment name. - // Would be nice to have this on for UmbracoIntegrationTest also but requires a lot more effort to resolve issues. - cfg.ValidateOnBuild = true; - cfg.ValidateScopes = true; - }); + Configuration = configBuilder.Build(); + }) + .ConfigureWebHost(builder => + { + // need to configure the IWebHostEnvironment too + builder.ConfigureServices((c, s) => c.HostingEnvironment = TestHelper.GetWebHostEnvironment()); - return builder; + // call startup + builder.Configure(app => Configure(app)); + }) + .ConfigureServices((_, services) => + { + ConfigureServices(services); + ConfigureTestSpecificServices(services); + services.AddUnique(CreateLoggerFactory()); + + if (!TestOptions.Boot) + { + // If boot is false, we don't want the CoreRuntime hosted service to start + // So we replace it with a Mock + services.AddUnique(Mock.Of()); + } + }) + .UseDefaultServiceProvider(cfg => + { + // These default to true *if* WebHostEnvironment.EnvironmentName == Development + // When running tests, EnvironmentName used to be null on the mock that we register into services. + // Enable opt in for tests so that validation occurs regardless of environment name. + // Would be nice to have this on for UmbracoIntegrationTest also but requires a lot more effort to resolve issues. + cfg.ValidateOnBuild = true; + cfg.ValidateScopes = true; + }); + + return hostBuilder; } /// @@ -157,7 +187,7 @@ namespace Umbraco.Cms.Tests.Integration.TestServerTest protected WebApplicationFactory Factory { get; private set; } - public override void ConfigureServices(IServiceCollection services) + private void ConfigureServices(IServiceCollection services) { services.AddTransient(); diff --git a/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index 7ec8a7fc14..915d2d7629 100644 --- a/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -128,7 +128,7 @@ namespace Umbraco.Cms.Tests.Integration.Testing UseTestDatabase(Services); } - private ILoggerFactory CreateLoggerFactory() + protected ILoggerFactory CreateLoggerFactory() { try { @@ -163,7 +163,7 @@ namespace Umbraco.Cms.Tests.Integration.Testing /// /// Create the Generic Host and execute startup ConfigureServices/Configure calls /// - public virtual IHostBuilder CreateHostBuilder() + protected virtual IHostBuilder CreateHostBuilder() { IHostBuilder hostBuilder = Host.CreateDefaultBuilder() @@ -180,9 +180,10 @@ namespace Umbraco.Cms.Tests.Integration.Testing Configuration = configBuilder.Build(); }) - .ConfigureServices((hostContext, services) => + .ConfigureServices((_, services) => { ConfigureServices(services); + ConfigureTestSpecificServices(services); services.AddUnique(CreateLoggerFactory()); if (!TestOptions.Boot) @@ -192,10 +193,15 @@ namespace Umbraco.Cms.Tests.Integration.Testing services.AddUnique(Mock.Of()); } }); + return hostBuilder; } - public virtual void ConfigureServices(IServiceCollection services) + protected virtual void ConfigureTestSpecificServices(IServiceCollection services) + { + } + + private void ConfigureServices(IServiceCollection services) { services.AddSingleton(TestHelper.DbProviderFactoryCreator); services.AddTransient(); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Events/EventAggregatorTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Events/EventAggregatorTests.cs index 6446bf542a..55429af147 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Events/EventAggregatorTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Events/EventAggregatorTests.cs @@ -14,9 +14,8 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Events [TestFixture] public class EventAggregatorTests : UmbracoTestServerTestBase { - public override void ConfigureServices(IServiceCollection services) + protected override void ConfigureTestSpecificServices(IServiceCollection services) { - base.ConfigureServices(services); services.AddScoped(); services.AddTransient, EventAggregatorTestNotificationHandler>(); } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/ExamineBaseTest.cs b/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/ExamineBaseTest.cs index bc1c6b8f02..7769f99d83 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/ExamineBaseTest.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/ExamineBaseTest.cs @@ -29,11 +29,8 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Examine.Lucene.UmbracoExamine protected IRuntimeState RunningRuntimeState { get; } = Mock.Of(x => x.Level == RuntimeLevel.Run); - public override void ConfigureServices(IServiceCollection services) - { - base.ConfigureServices(services); - services.AddSingleton(); - } + protected override void ConfigureTestSpecificServices(IServiceCollection services) + => services.AddSingleton(); /// /// Used to create and manage a testable index