using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NUnit.Framework;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Composing.LightInject;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Scoping;
using Umbraco.Core.Strings;
using Umbraco.Tests.Common.Builders;
using Umbraco.Tests.Integration.Extensions;
using Umbraco.Tests.Integration.Implementations;
using Umbraco.Extensions;
using Umbraco.Tests.Testing;
using Umbraco.Web;
using ILogger = Umbraco.Core.Logging.ILogger;
using Umbraco.Core.Runtime;
using Umbraco.Core;
using Moq;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
using System.Data.SqlClient;
using System.Data.Common;
using System.IO;
namespace Umbraco.Tests.Integration.Testing
{
///
/// Abstract class for integration tests
///
///
/// This will use a Host Builder to boot and install Umbraco ready for use
///
[SingleThreaded]
[NonParallelizable]
public abstract class UmbracoIntegrationTest
{
public static LightInjectContainer CreateUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory)
{
var container = UmbracoServiceProviderFactory.CreateServiceContainer();
serviceProviderFactory = new UmbracoServiceProviderFactory(container, false);
var umbracoContainer = serviceProviderFactory.GetContainer();
return umbracoContainer;
}
private List _testTeardown = null;
private List _fixtureTeardown = new List();
public void OnTestTearDown(Action tearDown)
{
if (_testTeardown == null)
_testTeardown = new List();
_testTeardown.Add(tearDown);
}
public void OnFixtureTearDown(Action tearDown) => _fixtureTeardown.Add(tearDown);
[OneTimeTearDown]
public void FixtureTearDown()
{
foreach (var a in _fixtureTeardown) a();
}
[TearDown]
public virtual void TearDown()
{
foreach (var a in _testTeardown) a();
_testTeardown = null;
}
[SetUp]
public virtual async Task Setup()
{
var hostBuilder = CreateHostBuilder();
var host = await hostBuilder.StartAsync();
Services = host.Services;
var app = new ApplicationBuilder(host.Services);
Configure(app);
}
#region Generic Host Builder and Runtime
///
/// Create the Generic Host and execute startup ConfigureServices/Configure calls
///
///
public virtual IHostBuilder CreateHostBuilder()
{
UmbracoContainer = CreateUmbracoContainer(out var serviceProviderFactory);
_serviceProviderFactory = serviceProviderFactory;
var hostBuilder = Host.CreateDefaultBuilder()
// IMPORTANT: We Cannot use UseStartup, there's all sorts of threads about this with testing. Although this can work
// if you want to setup your tests this way, it is a bit annoying to do that as the WebApplicationFactory will
// create separate Host instances. So instead of UseStartup, we just call ConfigureServices/Configure ourselves,
// and in the case of the UmbracoTestServerTestBase it will use the ConfigureWebHost to Configure the IApplicationBuilder directly.
//.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(GetType()); })
.UseUmbraco(_serviceProviderFactory)
.ConfigureAppConfiguration((context, configBuilder) =>
{
context.HostingEnvironment = TestHelper.GetWebHostEnvironment();
Configuration = context.Configuration;
configBuilder.AddInMemoryCollection(InMemoryConfiguration);
})
.ConfigureServices((hostContext, services) =>
{
ConfigureServices(services);
});
return hostBuilder;
}
///
/// Creates a instance for testing and registers an event handler for database install
///
///
///
///
///
///
///
///
///
///
///
///
public CoreRuntime CreateTestRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper,
ILogger logger, IProfiler profiler, Core.Hosting.IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo,
ITypeFinder typeFinder, AppCaches appCaches, IDbProviderFactoryCreator dbProviderFactoryCreator)
{
var runtime = CreateTestRuntime(configs,
umbracoVersion,
ioHelper,
logger,
profiler,
hostingEnvironment,
backOfficeInfo,
typeFinder,
appCaches,
dbProviderFactoryCreator,
TestHelper.MainDom, // SimpleMainDom
UseTestLocalDb // DB Installation event handler
);
return runtime;
}
///
/// Creates a instance for testing and registers an event handler for database install
///
///
///
///
///
///
///
///
///
///
///
///
/// The event handler used for DB installation
///
public static CoreRuntime CreateTestRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper,
ILogger logger, IProfiler profiler, Core.Hosting.IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo,
ITypeFinder typeFinder, AppCaches appCaches, IDbProviderFactoryCreator dbProviderFactoryCreator,
IMainDom mainDom, Action eventHandler)
{
var runtime = new CoreRuntime(
configs,
umbracoVersion,
ioHelper,
logger,
profiler,
Mock.Of(),
hostingEnvironment,
backOfficeInfo,
dbProviderFactoryCreator,
mainDom,
typeFinder,
appCaches);
runtime.RuntimeEssentials += (sender, args) => eventHandler(sender, args);
return runtime;
}
#endregion
#region IStartup
public virtual void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(TestHelper.DbProviderFactoryCreator);
var webHostEnvironment = TestHelper.GetWebHostEnvironment();
services.AddRequiredNetCoreServices(TestHelper, webHostEnvironment);
// Add it!
services.AddUmbracoConfiguration(Configuration);
services.AddUmbracoCore(
webHostEnvironment,
UmbracoContainer,
GetType().Assembly,
AppCaches.NoCache, // Disable caches for integration tests
TestHelper.GetLoggingConfiguration(),
CreateTestRuntime,
out _);
services.AddUmbracoWebComponents();
services.AddUmbracoRuntimeMinifier(Configuration);
services.AddUmbracoBackOffice();
services.AddUmbracoBackOfficeIdentity();
services.AddMvc();
services.AddSingleton(new ConsoleLogger