Gets first integration test moved, moves the test options to the common project, ensures that the LocalDb pool is updated on each test
This commit is contained in:
+5
-1
@@ -31,10 +31,14 @@ namespace Umbraco.Tests.Testing
|
||||
var test = TestContext.CurrentContext.Test;
|
||||
var typeName = test.ClassName;
|
||||
var methodName = test.MethodName;
|
||||
// this will only get types from whatever is already loaded in the app domain
|
||||
var type = Type.GetType(typeName, false);
|
||||
if (type == null)
|
||||
{
|
||||
type = ScanAssemblies
|
||||
// automatically add the executing and calling assemblies to the list to scan for this type
|
||||
var scanAssemblies = ScanAssemblies.Union(new[] {Assembly.GetExecutingAssembly(), Assembly.GetCallingAssembly()}).ToList();
|
||||
|
||||
type = scanAssemblies
|
||||
.Select(assembly => assembly.GetType(typeName, false))
|
||||
.FirstOrDefault(x => x != null);
|
||||
if (type == null)
|
||||
@@ -0,0 +1,61 @@
|
||||
namespace Umbraco.Tests.Testing
|
||||
{
|
||||
public static class UmbracoTestOptions
|
||||
{
|
||||
public enum Logger
|
||||
{
|
||||
/// <summary>
|
||||
/// pure mocks
|
||||
/// </summary>
|
||||
Mock,
|
||||
/// <summary>
|
||||
/// Serilog for tests
|
||||
/// </summary>
|
||||
Serilog,
|
||||
/// <summary>
|
||||
/// console logger
|
||||
/// </summary>
|
||||
Console
|
||||
}
|
||||
|
||||
public enum Database
|
||||
{
|
||||
/// <summary>
|
||||
/// no database
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// new empty database file for the entire fixture
|
||||
/// </summary>
|
||||
NewEmptyPerFixture,
|
||||
/// <summary>
|
||||
/// new empty database file per test
|
||||
/// </summary>
|
||||
NewEmptyPerTest,
|
||||
/// <summary>
|
||||
/// new database file with schema for the entire fixture
|
||||
/// </summary>
|
||||
NewSchemaPerFixture,
|
||||
/// <summary>
|
||||
/// new database file with schema per test
|
||||
/// </summary>
|
||||
NewSchemaPerTest
|
||||
}
|
||||
|
||||
public enum TypeLoader
|
||||
{
|
||||
/// <summary>
|
||||
/// the default, global type loader for tests
|
||||
/// </summary>
|
||||
Default,
|
||||
/// <summary>
|
||||
/// create one type loader for the feature
|
||||
/// </summary>
|
||||
PerFixture,
|
||||
/// <summary>
|
||||
/// create one type loader for each test
|
||||
/// </summary>
|
||||
PerTest
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Tests.Common;
|
||||
using Umbraco.Tests.Integration.Implementations;
|
||||
using Umbraco.Tests.Integration.Testing;
|
||||
|
||||
namespace Umbraco.Tests.Integration
|
||||
{
|
||||
@@ -82,7 +83,7 @@ namespace Umbraco.Tests.Integration
|
||||
// it means the container won't be disposed, and maybe other services? not sure.
|
||||
// In cases where we use it can we use IConfigureOptions? https://andrewlock.net/access-services-inside-options-and-startup-using-configureoptions/
|
||||
|
||||
var umbracoContainer = RuntimeTests.GetUmbracoContainer(out var serviceProviderFactory);
|
||||
var umbracoContainer = UmbracoIntegrationTest.GetUmbracoContainer(out var serviceProviderFactory);
|
||||
|
||||
IHostApplicationLifetime lifetime1 = null;
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using System.Data.SqlClient;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Configuration.Models;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Tests.Integration.Testing;
|
||||
using Umbraco.Tests.Testing;
|
||||
|
||||
namespace Umbraco.Tests.Integration.Extensions
|
||||
{
|
||||
public static class ApplicationBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a LocalDb instance to use for the test
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
/// <param name="dbFilePath"></param>
|
||||
/// <param name="integrationTest"></param>
|
||||
/// <returns></returns>
|
||||
public static IApplicationBuilder UseTestLocalDb(this IApplicationBuilder app,
|
||||
string dbFilePath,
|
||||
UmbracoIntegrationTest integrationTest)
|
||||
{
|
||||
// get the currently set db options
|
||||
var testOptions = TestOptionAttributeBase.GetTestOptions<UmbracoTestAttribute>();
|
||||
|
||||
if (testOptions.Database == UmbracoTestOptions.Database.None)
|
||||
return app;
|
||||
|
||||
// need to manually register this factory
|
||||
DbProviderFactories.RegisterFactory(Constants.DbProviderNames.SqlServer, SqlClientFactory.Instance);
|
||||
|
||||
if (!Directory.Exists(dbFilePath))
|
||||
Directory.CreateDirectory(dbFilePath);
|
||||
|
||||
var db = UmbracoIntegrationTest.GetOrCreate(dbFilePath,
|
||||
app.ApplicationServices.GetRequiredService<ILogger>(),
|
||||
app.ApplicationServices.GetRequiredService<IGlobalSettings>(),
|
||||
app.ApplicationServices.GetRequiredService<IUmbracoDatabaseFactory>());
|
||||
|
||||
switch (testOptions.Database)
|
||||
{
|
||||
case UmbracoTestOptions.Database.NewSchemaPerTest:
|
||||
|
||||
// Add teardown callback
|
||||
integrationTest.OnTestTearDown(() => db.Detach());
|
||||
|
||||
// New DB + Schema
|
||||
db.AttachSchema();
|
||||
|
||||
// We must re-configure our current factory since attaching a new LocalDb from the pool changes connection strings
|
||||
var dbFactory = app.ApplicationServices.GetRequiredService<IUmbracoDatabaseFactory>();
|
||||
if (!dbFactory.Configured)
|
||||
{
|
||||
dbFactory.Configure(db.ConnectionString, Umbraco.Core.Constants.DatabaseProviders.SqlServer);
|
||||
}
|
||||
|
||||
// In the case that we've initialized the schema, it means that we are installed so we'll want to ensure that
|
||||
// the runtime state is configured correctly so we'll force update the configuration flag and re-run the
|
||||
// runtime state checker.
|
||||
// TODO: This wouldn't be required if we don't store the Umbraco version in config
|
||||
|
||||
// right now we are an an 'Install' state
|
||||
var runtimeState = (RuntimeState)app.ApplicationServices.GetRequiredService<IRuntimeState>();
|
||||
Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level);
|
||||
|
||||
// dynamically change the config status
|
||||
var umbVersion = app.ApplicationServices.GetRequiredService<IUmbracoVersion>();
|
||||
var config = app.ApplicationServices.GetRequiredService<IConfiguration>();
|
||||
config[GlobalSettings.Prefix + "ConfigurationStatus"] = umbVersion.SemanticVersion.ToString();
|
||||
|
||||
// re-run the runtime level check
|
||||
var profilingLogger = app.ApplicationServices.GetRequiredService<IProfilingLogger>();
|
||||
runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger);
|
||||
|
||||
Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level);
|
||||
|
||||
break;
|
||||
case UmbracoTestOptions.Database.NewEmptyPerTest:
|
||||
|
||||
// Add teardown callback
|
||||
integrationTest.OnTestTearDown(() => db.Detach());
|
||||
|
||||
db.AttachEmpty();
|
||||
|
||||
break;
|
||||
case UmbracoTestOptions.Database.NewSchemaPerFixture:
|
||||
|
||||
// Add teardown callback
|
||||
integrationTest.OnFixtureTearDown(() => db.Detach());
|
||||
|
||||
break;
|
||||
case UmbracoTestOptions.Database.NewEmptyPerFixture:
|
||||
|
||||
// Add teardown callback
|
||||
integrationTest.OnFixtureTearDown(() => db.Detach());
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(testOptions), testOptions, null);
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Tests.Integration.Implementations;
|
||||
|
||||
namespace Umbraco.Tests.Integration.Extensions
|
||||
{
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// These services need to be manually added because they do not get added by the generic host
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="testHelper"></param>
|
||||
/// <param name="webHostEnvironment"></param>
|
||||
public static void AddRequiredNetCoreServices(this IServiceCollection services, TestHelper testHelper, IWebHostEnvironment webHostEnvironment)
|
||||
{
|
||||
services.AddSingleton<IHttpContextAccessor>(x => testHelper.GetHttpContextAccessor());
|
||||
// the generic host does add IHostEnvironment but not this one because we are not actually in a web context
|
||||
services.AddSingleton<IWebHostEnvironment>(x => webHostEnvironment);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Data.SqlClient;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Configuration.Models;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Tests.Integration.Testing;
|
||||
|
||||
namespace Umbraco.Tests.Integration.Implementations
|
||||
{
|
||||
public static class ApplicationBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a LocalDb instance to use for the test
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
/// <param name="dbFilePath"></param>
|
||||
/// <param name="createNewDb">
|
||||
/// Default is true - meaning a brand new database is created for this test. If this is false it will try to
|
||||
/// re-use an existing database that was already created as part of this test fixture.
|
||||
/// // TODO Implement the 'false' behavior
|
||||
/// </param>
|
||||
/// <param name="initializeSchema">
|
||||
/// Default is true - meaning a database schema will be created for this test if it's a new database. If this is false
|
||||
/// it will just create an empty database.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public static IApplicationBuilder UseTestLocalDb(this IApplicationBuilder app,
|
||||
string dbFilePath,
|
||||
bool createNewDb = true,
|
||||
bool initializeSchema = true)
|
||||
{
|
||||
// need to manually register this factory
|
||||
DbProviderFactories.RegisterFactory(Constants.DbProviderNames.SqlServer, SqlClientFactory.Instance);
|
||||
|
||||
if (!Directory.Exists(dbFilePath))
|
||||
Directory.CreateDirectory(dbFilePath);
|
||||
|
||||
var db = LocalDbTestDatabase.Get(dbFilePath,
|
||||
app.ApplicationServices.GetRequiredService<ILogger>(),
|
||||
app.ApplicationServices.GetRequiredService<IGlobalSettings>(),
|
||||
app.ApplicationServices.GetRequiredService<IUmbracoDatabaseFactory>());
|
||||
|
||||
if (initializeSchema)
|
||||
{
|
||||
// New DB + Schema
|
||||
db.AttachSchema();
|
||||
|
||||
// In the case that we've initialized the schema, it means that we are installed so we'll want to ensure that
|
||||
// the runtime state is configured correctly so we'll force update the configuration flag and re-run the
|
||||
// runtime state checker.
|
||||
// TODO: This wouldn't be required if we don't store the Umbraco version in config
|
||||
|
||||
// right now we are an an 'Install' state
|
||||
var runtimeState = (RuntimeState)app.ApplicationServices.GetRequiredService<IRuntimeState>();
|
||||
Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level);
|
||||
|
||||
// dynamically change the config status
|
||||
var umbVersion = app.ApplicationServices.GetRequiredService<IUmbracoVersion>();
|
||||
var config = app.ApplicationServices.GetRequiredService<IConfiguration>();
|
||||
config[GlobalSettings.Prefix + "ConfigurationStatus"] = umbVersion.SemanticVersion.ToString();
|
||||
|
||||
// re-run the runtime level check
|
||||
var dbFactory = app.ApplicationServices.GetRequiredService<IUmbracoDatabaseFactory>();
|
||||
var profilingLogger = app.ApplicationServices.GetRequiredService<IProfilingLogger>();
|
||||
runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger);
|
||||
|
||||
Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
db.AttachEmpty();
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+27
-27
@@ -1,29 +1,29 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Persistence.Repositories.Implement;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.Integration.Testing;
|
||||
using Umbraco.Tests.Testing;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.Persistence.Repositories
|
||||
namespace Umbraco.Tests.Integration.Persistence.Repositories
|
||||
{
|
||||
[TestFixture]
|
||||
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, Logger = UmbracoTestOptions.Logger.Console)]
|
||||
public class AuditRepositoryTest : TestWithDatabaseBase
|
||||
public class AuditRepositoryTest : UmbracoIntegrationTest
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void Can_Add_Audit_Entry()
|
||||
{
|
||||
var sp = TestObjects.GetScopeProvider(Logger);
|
||||
using (var scope = sp.CreateScope())
|
||||
var sp = ScopeProvider;
|
||||
using (var scope = ScopeProvider.CreateScope())
|
||||
{
|
||||
var repo = new AuditRepository((IScopeAccessor) sp, Logger);
|
||||
repo.Save(new AuditItem(-1, AuditType.System, -1, ObjectTypes.GetName(UmbracoObjectTypes.Document), "This is a System audit trail"));
|
||||
var repo = new AuditRepository((IScopeAccessor)sp, Logger);
|
||||
repo.Save(new AuditItem(-1, AuditType.System, -1, UmbracoObjectTypes.Document.GetName(), "This is a System audit trail"));
|
||||
|
||||
var dtos = scope.Database.Fetch<LogDto>("WHERE id > -1");
|
||||
|
||||
@@ -35,15 +35,15 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
[Test]
|
||||
public void Get_Paged_Items()
|
||||
{
|
||||
var sp = TestObjects.GetScopeProvider(Logger);
|
||||
var sp = ScopeProvider;
|
||||
using (var scope = sp.CreateScope())
|
||||
{
|
||||
var repo = new AuditRepository((IScopeAccessor) sp, Logger);
|
||||
var repo = new AuditRepository((IScopeAccessor)sp, Logger);
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
repo.Save(new AuditItem(i, AuditType.New, -1, ObjectTypes.GetName(UmbracoObjectTypes.Document), $"Content {i} created"));
|
||||
repo.Save(new AuditItem(i, AuditType.Publish, -1, ObjectTypes.GetName(UmbracoObjectTypes.Document), $"Content {i} published"));
|
||||
repo.Save(new AuditItem(i, AuditType.New, -1, UmbracoObjectTypes.Document.GetName(), $"Content {i} created"));
|
||||
repo.Save(new AuditItem(i, AuditType.Publish, -1, UmbracoObjectTypes.Document.GetName(), $"Content {i} published"));
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
@@ -51,7 +51,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
using (var scope = sp.CreateScope())
|
||||
{
|
||||
var repo = new AuditRepository((IScopeAccessor) sp, Logger);
|
||||
var repo = new AuditRepository((IScopeAccessor)sp, Logger);
|
||||
|
||||
var page = repo.GetPagedResultsByQuery(sp.SqlContext.Query<IAuditItem>(), 0, 10, out var total, Direction.Descending, null, null);
|
||||
|
||||
@@ -63,15 +63,15 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
[Test]
|
||||
public void Get_Paged_Items_By_User_Id_With_Query_And_Filter()
|
||||
{
|
||||
var sp = TestObjects.GetScopeProvider(Logger);
|
||||
var sp = ScopeProvider;
|
||||
using (var scope = sp.CreateScope())
|
||||
{
|
||||
var repo = new AuditRepository((IScopeAccessor)sp, Logger);
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
repo.Save(new AuditItem(i, AuditType.New, -1, ObjectTypes.GetName(UmbracoObjectTypes.Document), $"Content {i} created"));
|
||||
repo.Save(new AuditItem(i, AuditType.Publish, -1, ObjectTypes.GetName(UmbracoObjectTypes.Document), $"Content {i} published"));
|
||||
repo.Save(new AuditItem(i, AuditType.New, -1, UmbracoObjectTypes.Document.GetName(), $"Content {i} created"));
|
||||
repo.Save(new AuditItem(i, AuditType.Publish, -1, UmbracoObjectTypes.Document.GetName(), $"Content {i} published"));
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
@@ -106,15 +106,15 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
[Test]
|
||||
public void Get_Paged_Items_With_AuditType_Filter()
|
||||
{
|
||||
var sp = TestObjects.GetScopeProvider(Logger);
|
||||
var sp = ScopeProvider;
|
||||
using (var scope = sp.CreateScope())
|
||||
{
|
||||
var repo = new AuditRepository((IScopeAccessor) sp, Logger);
|
||||
var repo = new AuditRepository((IScopeAccessor)sp, Logger);
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
repo.Save(new AuditItem(i, AuditType.New, -1, ObjectTypes.GetName(UmbracoObjectTypes.Document), $"Content {i} created"));
|
||||
repo.Save(new AuditItem(i, AuditType.Publish, -1, ObjectTypes.GetName(UmbracoObjectTypes.Document), $"Content {i} published"));
|
||||
repo.Save(new AuditItem(i, AuditType.New, -1, UmbracoObjectTypes.Document.GetName(), $"Content {i} created"));
|
||||
repo.Save(new AuditItem(i, AuditType.Publish, -1, UmbracoObjectTypes.Document.GetName(), $"Content {i} published"));
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
@@ -122,10 +122,10 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
using (var scope = sp.CreateScope())
|
||||
{
|
||||
var repo = new AuditRepository((IScopeAccessor) sp, Logger);
|
||||
var repo = new AuditRepository((IScopeAccessor)sp, Logger);
|
||||
|
||||
var page = repo.GetPagedResultsByQuery(sp.SqlContext.Query<IAuditItem>(), 0, 9, out var total, Direction.Descending,
|
||||
new[] {AuditType.Publish}, null)
|
||||
new[] { AuditType.Publish }, null)
|
||||
.ToArray();
|
||||
|
||||
Assert.AreEqual(9, page.Length);
|
||||
@@ -137,15 +137,15 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
[Test]
|
||||
public void Get_Paged_Items_With_Custom_Filter()
|
||||
{
|
||||
var sp = TestObjects.GetScopeProvider(Logger);
|
||||
var sp = ScopeProvider;
|
||||
using (var scope = sp.CreateScope())
|
||||
{
|
||||
var repo = new AuditRepository((IScopeAccessor) sp, Logger);
|
||||
var repo = new AuditRepository((IScopeAccessor)sp, Logger);
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
repo.Save(new AuditItem(i, AuditType.New, -1, ObjectTypes.GetName(UmbracoObjectTypes.Document), "Content created"));
|
||||
repo.Save(new AuditItem(i, AuditType.Publish, -1, ObjectTypes.GetName(UmbracoObjectTypes.Document), "Content published"));
|
||||
repo.Save(new AuditItem(i, AuditType.New, -1, UmbracoObjectTypes.Document.GetName(), "Content created"));
|
||||
repo.Save(new AuditItem(i, AuditType.Publish, -1, UmbracoObjectTypes.Document.GetName(), "Content published"));
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
@@ -153,7 +153,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
using (var scope = sp.CreateScope())
|
||||
{
|
||||
var repo = new AuditRepository((IScopeAccessor) sp, Logger);
|
||||
var repo = new AuditRepository((IScopeAccessor)sp, Logger);
|
||||
|
||||
var page = repo.GetPagedResultsByQuery(sp.SqlContext.Query<IAuditItem>(), 0, 8, out var total, Direction.Descending,
|
||||
null, sp.SqlContext.Query<IAuditItem>().Where(item => item.Comment == "Content created"))
|
||||
@@ -1,30 +1,21 @@
|
||||
using LightInject;
|
||||
using LightInject.Microsoft.DependencyInjection;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Umbraco.Configuration.Models;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Composing.LightInject;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Migrations.Install;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Runtime;
|
||||
using Umbraco.Tests.Common;
|
||||
using Umbraco.Tests.Integration.Extensions;
|
||||
using Umbraco.Tests.Integration.Implementations;
|
||||
using Umbraco.Tests.Integration.Testing;
|
||||
using Umbraco.Web.BackOffice.AspNetCore;
|
||||
using static Umbraco.Core.Migrations.Install.DatabaseBuilder;
|
||||
|
||||
namespace Umbraco.Tests.Integration
|
||||
{
|
||||
@@ -39,10 +30,11 @@ namespace Umbraco.Tests.Integration
|
||||
MyComposer.Reset();
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
public void FixtureTearDown()
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
|
||||
MyComponent.Reset();
|
||||
MyComposer.Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -95,7 +87,7 @@ namespace Umbraco.Tests.Integration
|
||||
[Test]
|
||||
public async Task AddUmbracoCore()
|
||||
{
|
||||
var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory);
|
||||
var umbracoContainer = UmbracoIntegrationTest.GetUmbracoContainer(out var serviceProviderFactory);
|
||||
var testHelper = new TestHelper();
|
||||
|
||||
var hostBuilder = new HostBuilder()
|
||||
@@ -103,7 +95,7 @@ namespace Umbraco.Tests.Integration
|
||||
.ConfigureServices((hostContext, services) =>
|
||||
{
|
||||
var webHostEnvironment = testHelper.GetWebHostEnvironment();
|
||||
AddRequiredNetCoreServices(services, testHelper, webHostEnvironment);
|
||||
services.AddRequiredNetCoreServices(testHelper, webHostEnvironment);
|
||||
|
||||
// Add it!
|
||||
services.AddUmbracoConfiguration(hostContext.Configuration);
|
||||
@@ -134,7 +126,7 @@ namespace Umbraco.Tests.Integration
|
||||
[Test]
|
||||
public async Task UseUmbracoCore()
|
||||
{
|
||||
var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory);
|
||||
var umbracoContainer = UmbracoIntegrationTest.GetUmbracoContainer(out var serviceProviderFactory);
|
||||
var testHelper = new TestHelper();
|
||||
|
||||
var hostBuilder = new HostBuilder()
|
||||
@@ -142,7 +134,7 @@ namespace Umbraco.Tests.Integration
|
||||
.ConfigureServices((hostContext, services) =>
|
||||
{
|
||||
var webHostEnvironment = testHelper.GetWebHostEnvironment();
|
||||
AddRequiredNetCoreServices(services, testHelper, webHostEnvironment);
|
||||
services.AddRequiredNetCoreServices(testHelper, webHostEnvironment);
|
||||
|
||||
// Add it!
|
||||
services.AddUmbracoConfiguration(hostContext.Configuration);
|
||||
@@ -169,56 +161,6 @@ namespace Umbraco.Tests.Integration
|
||||
Assert.IsTrue(MyComponent.IsTerminated);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Install_Database()
|
||||
{
|
||||
var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory);
|
||||
var testHelper = new TestHelper();
|
||||
|
||||
var hostBuilder = new HostBuilder()
|
||||
.UseUmbraco(serviceProviderFactory)
|
||||
.ConfigureServices((hostContext, services) =>
|
||||
{
|
||||
var webHostEnvironment = testHelper.GetWebHostEnvironment();
|
||||
AddRequiredNetCoreServices(services, testHelper, webHostEnvironment);
|
||||
|
||||
// Add it!
|
||||
services.AddUmbracoConfiguration(hostContext.Configuration);
|
||||
services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly);
|
||||
});
|
||||
|
||||
var host = await hostBuilder.StartAsync();
|
||||
var app = new ApplicationBuilder(host.Services);
|
||||
|
||||
// This will create a db, install the schema and ensure the app is configured to run
|
||||
app.UseTestLocalDb(Path.Combine(testHelper.CurrentAssemblyDirectory, "LocalDb"));
|
||||
|
||||
app.UseUmbracoCore();
|
||||
|
||||
var runtimeState = app.ApplicationServices.GetRequiredService<IRuntimeState>();
|
||||
Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level);
|
||||
}
|
||||
|
||||
internal static LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory)
|
||||
{
|
||||
var container = UmbracoServiceProviderFactory.CreateServiceContainer();
|
||||
serviceProviderFactory = new UmbracoServiceProviderFactory(container);
|
||||
var umbracoContainer = serviceProviderFactory.GetContainer();
|
||||
return umbracoContainer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// These services need to be manually added because they do not get added by the generic host
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="testHelper"></param>
|
||||
/// <param name="webHostEnvironment"></param>
|
||||
private void AddRequiredNetCoreServices(IServiceCollection services, TestHelper testHelper, IWebHostEnvironment webHostEnvironment)
|
||||
{
|
||||
services.AddSingleton<IHttpContextAccessor>(x => testHelper.GetHttpContextAccessor());
|
||||
// the generic host does add IHostEnvironment but not this one because we are not actually in a web context
|
||||
services.AddSingleton<IWebHostEnvironment>(x => webHostEnvironment);
|
||||
}
|
||||
|
||||
[RuntimeLevel(MinLevel = RuntimeLevel.Install)]
|
||||
public class MyComposer : IUserComposer
|
||||
|
||||
@@ -17,16 +17,8 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
/// <summary>
|
||||
/// Manages a pool of LocalDb databases for integration testing
|
||||
/// </summary>
|
||||
internal class LocalDbTestDatabase
|
||||
public class LocalDbTestDatabase
|
||||
{
|
||||
public static LocalDbTestDatabase Get(string filesPath, ILogger logger, IGlobalSettings globalSettings, IUmbracoDatabaseFactory dbFactory)
|
||||
{
|
||||
var localDb = new LocalDb();
|
||||
if (localDb.IsAvailable == false)
|
||||
throw new InvalidOperationException("LocalDB is not available.");
|
||||
return new LocalDbTestDatabase(logger, globalSettings, localDb, filesPath, dbFactory);
|
||||
}
|
||||
|
||||
public const string InstanceName = "UmbracoTests";
|
||||
public const string DatabaseName = "UmbracoTests";
|
||||
|
||||
@@ -43,7 +35,8 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
private static DatabasePool _schemaPool;
|
||||
private DatabasePool _currentPool;
|
||||
|
||||
public LocalDbTestDatabase(ILogger logger, IGlobalSettings globalSettings, LocalDb localDb, string filesPath, IUmbracoDatabaseFactory dbFactory)
|
||||
//It's internal because `Umbraco.Core.Persistence.LocalDb` is internal
|
||||
internal LocalDbTestDatabase(ILogger logger, IGlobalSettings globalSettings, LocalDb localDb, string filesPath, IUmbracoDatabaseFactory dbFactory)
|
||||
{
|
||||
_umbracoVersion = new UmbracoVersion();
|
||||
_logger = logger;
|
||||
@@ -328,5 +321,6 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
while (_readyQueue.TryTake(out i)) { }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Composing.LightInject;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Tests.Integration.Extensions;
|
||||
using Umbraco.Tests.Integration.Implementations;
|
||||
using Umbraco.Tests.Testing;
|
||||
using Umbraco.Web.BackOffice.AspNetCore;
|
||||
|
||||
namespace Umbraco.Tests.Integration.Testing
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract class for integration tests
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will use a Host Builder to boot and install Umbraco ready for use
|
||||
/// </remarks>
|
||||
[SingleThreaded]
|
||||
[NonParallelizable]
|
||||
public abstract class UmbracoIntegrationTest
|
||||
{
|
||||
public static LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory)
|
||||
{
|
||||
var container = UmbracoServiceProviderFactory.CreateServiceContainer();
|
||||
serviceProviderFactory = new UmbracoServiceProviderFactory(container);
|
||||
var umbracoContainer = serviceProviderFactory.GetContainer();
|
||||
return umbracoContainer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get or create an instance of <see cref="LocalDbTestDatabase"/>
|
||||
/// </summary>
|
||||
/// <param name="filesPath"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="globalSettings"></param>
|
||||
/// <param name="dbFactory"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// There must only be ONE instance shared between all tests in a session
|
||||
/// </remarks>
|
||||
public static LocalDbTestDatabase GetOrCreate(string filesPath, ILogger logger, IGlobalSettings globalSettings, IUmbracoDatabaseFactory dbFactory)
|
||||
{
|
||||
lock (_dbLocker)
|
||||
{
|
||||
if (_dbInstance != null) return _dbInstance;
|
||||
|
||||
var localDb = new LocalDb();
|
||||
if (localDb.IsAvailable == false)
|
||||
throw new InvalidOperationException("LocalDB is not available.");
|
||||
_dbInstance = new LocalDbTestDatabase(logger, globalSettings, localDb, filesPath, dbFactory);
|
||||
return _dbInstance;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly object _dbLocker = new object();
|
||||
private static LocalDbTestDatabase _dbInstance;
|
||||
|
||||
private readonly List<Action> _testTeardown = new List<Action>();
|
||||
private readonly List<Action> _fixtureTeardown = new List<Action>();
|
||||
|
||||
public void OnTestTearDown(Action tearDown)
|
||||
{
|
||||
_testTeardown.Add(tearDown);
|
||||
}
|
||||
|
||||
public void OnFixtureTearDown(Action tearDown)
|
||||
{
|
||||
_fixtureTeardown.Add(tearDown);
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
public void FixtureTearDown()
|
||||
{
|
||||
// call all registered callbacks
|
||||
foreach (var action in _fixtureTeardown)
|
||||
{
|
||||
action();
|
||||
}
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
// call all registered callbacks
|
||||
foreach (var action in _testTeardown)
|
||||
{
|
||||
action();
|
||||
}
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public async Task Setup()
|
||||
{
|
||||
var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory);
|
||||
var testHelper = new TestHelper();
|
||||
|
||||
var hostBuilder = new HostBuilder()
|
||||
.UseUmbraco(serviceProviderFactory)
|
||||
.ConfigureServices((hostContext, services) =>
|
||||
{
|
||||
var webHostEnvironment = testHelper.GetWebHostEnvironment();
|
||||
services.AddRequiredNetCoreServices(testHelper, webHostEnvironment);
|
||||
|
||||
// Add it!
|
||||
services.AddUmbracoConfiguration(hostContext.Configuration);
|
||||
services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly);
|
||||
});
|
||||
|
||||
var host = await hostBuilder.StartAsync();
|
||||
var app = new ApplicationBuilder(host.Services);
|
||||
Services = app.ApplicationServices;
|
||||
|
||||
// This will create a db, install the schema and ensure the app is configured to run
|
||||
app.UseTestLocalDb(Path.Combine(testHelper.CurrentAssemblyDirectory, "LocalDb"), this);
|
||||
|
||||
app.UseUmbracoCore();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the DI container
|
||||
/// </summary>
|
||||
protected IServiceProvider Services { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="IScopeProvider"/>
|
||||
/// </summary>
|
||||
protected IScopeProvider ScopeProvider => Services.GetRequiredService<IScopeProvider>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="IScopeAccessor"/>
|
||||
/// </summary>
|
||||
protected IScopeAccessor ScopeAccessor => Services.GetRequiredService<IScopeAccessor>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="ILogger"/>
|
||||
/// </summary>
|
||||
protected ILogger Logger => Services.GetRequiredService<ILogger>();
|
||||
}
|
||||
}
|
||||
@@ -252,8 +252,8 @@ namespace Umbraco.Tests.TestHelpers
|
||||
TestHelper.DbProviderFactoryCreator);
|
||||
}
|
||||
|
||||
typeFinder = typeFinder ?? new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
fileSystems = fileSystems ?? new FileSystems(Current.Factory, logger, TestHelper.IOHelper, SettingsForTests.GenerateMockGlobalSettings());
|
||||
typeFinder ??= new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
fileSystems ??= new FileSystems(Current.Factory, logger, TestHelper.IOHelper, SettingsForTests.GenerateMockGlobalSettings());
|
||||
var coreDebug = TestHelper.CoreDebugSettings;
|
||||
var mediaFileSystem = Mock.Of<IMediaFileSystem>();
|
||||
var scopeProvider = new ScopeProvider(databaseFactory, fileSystems, coreDebug, mediaFileSystem, logger, typeFinder, NoAppCache.Instance);
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
namespace Umbraco.Tests.Testing
|
||||
{
|
||||
public static class UmbracoTestOptions
|
||||
{
|
||||
public enum Logger
|
||||
{
|
||||
// pure mocks
|
||||
Mock,
|
||||
// Serilog for tests
|
||||
Serilog,
|
||||
// console logger
|
||||
Console
|
||||
}
|
||||
|
||||
public enum Database
|
||||
{
|
||||
// no database
|
||||
None,
|
||||
// new empty database file for the entire feature
|
||||
NewEmptyPerFixture,
|
||||
// new empty database file per test
|
||||
NewEmptyPerTest,
|
||||
// new database file with schema for the entire feature
|
||||
NewSchemaPerFixture,
|
||||
// new database file with schema per test
|
||||
NewSchemaPerTest
|
||||
}
|
||||
|
||||
public enum TypeLoader
|
||||
{
|
||||
// the default, global type loader for tests
|
||||
Default,
|
||||
// create one type loader for the feature
|
||||
PerFixture,
|
||||
// create one type loader for each test
|
||||
PerTest
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,11 +231,8 @@
|
||||
<Compile Include="Persistence\NPocoTests\NPocoSqlExtensionsTests.cs" />
|
||||
<Compile Include="Persistence\UnitOfWorkTests.cs" />
|
||||
<Compile Include="Persistence\Repositories\RedirectUrlRepositoryTests.cs" />
|
||||
<Compile Include="Testing\TestOptionAttributeBase.cs" />
|
||||
<Compile Include="Testing\UmbracoTestAttribute.cs" />
|
||||
<Compile Include="Testing\UmbracoTestBase.cs" />
|
||||
<Compile Include="TestHelpers\Entities\MockedPropertyTypes.cs" />
|
||||
<Compile Include="Testing\UmbracoTestOptions.cs" />
|
||||
<Compile Include="CoreThings\TryConvertToTests.cs" />
|
||||
<Compile Include="TestHelpers\TestObjects-Mocks.cs" />
|
||||
<Compile Include="TestHelpers\TestObjects.cs" />
|
||||
@@ -267,7 +264,6 @@
|
||||
<Compile Include="Web\ModelStateExtensionsTests.cs" />
|
||||
<Compile Include="Web\Mvc\RenderIndexActionSelectorAttributeTests.cs" />
|
||||
<Compile Include="Persistence\NPocoTests\PetaPocoCachesTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\AuditRepositoryTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\DomainRepositoryTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\PartialViewRepositoryTests.cs" />
|
||||
<Compile Include="Persistence\Repositories\PublicAccessRepositoryTest.cs" />
|
||||
|
||||
Reference in New Issue
Block a user