diff --git a/src/Umbraco.Configuration/Models/GlobalSettings.cs b/src/Umbraco.Configuration/Models/GlobalSettings.cs
index 4dc764a974..ed1b4e58a2 100644
--- a/src/Umbraco.Configuration/Models/GlobalSettings.cs
+++ b/src/Umbraco.Configuration/Models/GlobalSettings.cs
@@ -12,7 +12,7 @@ namespace Umbraco.Configuration.Models
///
internal class GlobalSettings : IGlobalSettings
{
- private const string Prefix = Constants.Configuration.ConfigPrefix + "Global:";
+ public const string Prefix = Constants.Configuration.ConfigPrefix + "Global:";
internal const string
StaticReservedPaths = "~/app_plugins/,~/install/,~/mini-profiler-resources/,"; //must end with a comma!
diff --git a/src/Umbraco.Configuration/Umbraco.Configuration.csproj b/src/Umbraco.Configuration/Umbraco.Configuration.csproj
index 88bb3639d0..2337ea24f8 100644
--- a/src/Umbraco.Configuration/Umbraco.Configuration.csproj
+++ b/src/Umbraco.Configuration/Umbraco.Configuration.csproj
@@ -32,4 +32,10 @@
+
+
+ <_Parameter1>Umbraco.Tests.Integration
+
+
+
diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs
index dd96e6edd7..35154a9f50 100644
--- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs
+++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Configuration
private readonly IGlobalSettings _globalSettings;
public UmbracoVersion(IGlobalSettings globalSettings)
- :this()
+ : this()
{
_globalSettings = globalSettings;
}
@@ -55,7 +55,7 @@ namespace Umbraco.Core.Configuration
/// Is the one that the CLR checks for compatibility. Therefore, it changes only on
/// hard-breaking changes (for instance, on new major versions).
///
- public Version AssemblyVersion {get; }
+ public Version AssemblyVersion { get; }
///
/// Gets the assembly file version of the Umbraco code.
@@ -83,11 +83,13 @@ namespace Umbraco.Core.Configuration
/// and changes during an upgrade. The executing code version changes when new code is
/// deployed. The site/files version changes during an upgrade.
///
- public SemVersion LocalVersion {
+ public SemVersion LocalVersion
+ {
get
{
var value = _globalSettings.ConfigurationStatus;
return value.IsNullOrWhiteSpace() ? null : SemVersion.TryParse(value, out var semver) ? semver : null;
- } }
+ }
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreator.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreator.cs
index 8a79cca403..921ba0b3d5 100644
--- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreator.cs
+++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreator.cs
@@ -130,7 +130,7 @@ namespace Umbraco.Core.Migrations.Install
if (e.Cancel == false)
{
- var dataCreation = new DatabaseDataCreator(_database, _logger,_umbracoVersion, _globalSettings);
+ var dataCreation = new DatabaseDataCreator(_database, _logger, _umbracoVersion, _globalSettings);
foreach (var table in OrderedTables)
CreateTable(false, table, dataCreation);
}
@@ -451,7 +451,7 @@ namespace Umbraco.Core.Migrations.Install
//Execute the Create Table sql
var created = _database.Execute(new Sql(createSql));
- _logger.Info("Create Table {TableName} ({Created}): \n {Sql}", tableName, created, createSql);
+ _logger.Info("Create Table {TableName} ({Created}): \n {Sql}", tableName, created, createSql);
//If any statements exists for the primary key execute them here
if (string.IsNullOrEmpty(createPrimaryKeySql) == false)
@@ -487,11 +487,11 @@ namespace Umbraco.Core.Migrations.Install
if (overwrite)
{
- _logger.Info("Table {TableName} was recreated", tableName);
+ _logger.Info("Table {TableName} was recreated", tableName);
}
else
{
- _logger.Info("New table {TableName} was created", tableName);
+ _logger.Info("New table {TableName} was created", tableName);
}
}
diff --git a/src/Umbraco.Infrastructure/Persistence/LocalDb.cs b/src/Umbraco.Infrastructure/Persistence/LocalDb.cs
index 55d6565344..4ec233e17f 100644
--- a/src/Umbraco.Infrastructure/Persistence/LocalDb.cs
+++ b/src/Umbraco.Infrastructure/Persistence/LocalDb.cs
@@ -253,6 +253,11 @@ namespace Umbraco.Core.Persistence
_masterCstr = $@"Server=(localdb)\{instanceName};Integrated Security=True;";
}
+ public static string GetConnectionString(string instanceName, string databaseName)
+ {
+ return $@"Server=(localdb)\{instanceName};Integrated Security=True;Database={databaseName};";
+ }
+
///
/// Gets a LocalDb connection string.
///
diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserGroupRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserGroupRepository.cs
index 07cfbb05a8..863f3dc455 100644
--- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserGroupRepository.cs
+++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserGroupRepository.cs
@@ -319,7 +319,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
private void PersistAllowedSections(IUserGroup entity)
{
- var userGroup = (UserGroup) entity;
+ var userGroup = entity;
// First delete all
Database.Delete("WHERE UserGroupId = @UserGroupId", new { UserGroupId = userGroup.Id });
diff --git a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabase.cs b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabase.cs
index ea3d603f95..a4b4afbe25 100644
--- a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabase.cs
+++ b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabase.cs
@@ -28,6 +28,7 @@ namespace Umbraco.Core.Persistence
private readonly RetryPolicy _connectionRetryPolicy;
private readonly RetryPolicy _commandRetryPolicy;
private readonly Guid _instanceGuid = Guid.NewGuid();
+ private List _commands;
#region Ctor
@@ -162,6 +163,14 @@ namespace Umbraco.Core.Persistence
///
public int SqlCount { get; private set; }
+ internal bool LogCommands
+ {
+ get => _commands != null;
+ set => _commands = value ? new List() : null;
+ }
+
+ internal IEnumerable Commands => _commands;
+
public int BulkInsertRecords(IEnumerable records)
{
return _bulkSqlInsertProvider.BulkInsertRecords(this, records);
@@ -267,9 +276,43 @@ namespace Umbraco.Core.Persistence
if (_enableCount)
SqlCount++;
+ _commands?.Add(new CommandInfo(cmd));
+
base.OnExecutedCommand(cmd);
}
#endregion
+
+ // used for tracking commands
+ public class CommandInfo
+ {
+ public CommandInfo(IDbCommand cmd)
+ {
+ Text = cmd.CommandText;
+ var parameters = new List();
+ foreach (IDbDataParameter parameter in cmd.Parameters) parameters.Add(new ParameterInfo(parameter));
+ Parameters = parameters.ToArray();
+ }
+
+ public string Text { get; }
+ public ParameterInfo[] Parameters { get; }
+ }
+
+ // used for tracking commands
+ public class ParameterInfo
+ {
+ public ParameterInfo(IDbDataParameter parameter)
+ {
+ Name = parameter.ParameterName;
+ Value = parameter.Value;
+ DbType = parameter.DbType;
+ Size = parameter.Size;
+ }
+
+ public string Name { get; }
+ public object Value { get; }
+ public DbType DbType { get; }
+ public int Size { get; }
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs
index a93c8db409..837fe6cba3 100644
--- a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs
+++ b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs
@@ -29,7 +29,6 @@ namespace Umbraco.Core.Persistence
{
private readonly IDbProviderFactoryCreator _dbProviderFactoryCreator;
private readonly IGlobalSettings _globalSettings;
- private readonly IConnectionStrings _connectionStrings;
private readonly Lazy _mappers;
private readonly ILogger _logger;
@@ -37,7 +36,6 @@ namespace Umbraco.Core.Persistence
private DatabaseFactory _npocoDatabaseFactory;
private IPocoDataFactory _pocoDataFactory;
- private string _connectionString;
private string _providerName;
private DatabaseType _databaseType;
private ISqlSyntaxProvider _sqlSyntax;
@@ -73,7 +71,7 @@ namespace Umbraco.Core.Persistence
///
/// Used by core runtime.
public UmbracoDatabaseFactory(ILogger logger, IGlobalSettings globalSettings, IConnectionStrings connectionStrings, Lazy mappers,IDbProviderFactoryCreator dbProviderFactoryCreator)
- : this(Constants.System.UmbracoConnectionName, globalSettings, connectionStrings, logger, mappers, dbProviderFactoryCreator)
+ : this(logger, globalSettings, connectionStrings, Constants.System.UmbracoConnectionName, mappers, dbProviderFactoryCreator)
{
}
@@ -82,13 +80,12 @@ namespace Umbraco.Core.Persistence
/// Initializes a new instance of the .
///
/// Used by the other ctor and in tests.
- public UmbracoDatabaseFactory(string connectionStringName, IGlobalSettings globalSettings, IConnectionStrings connectionStrings, ILogger logger, Lazy mappers, IDbProviderFactoryCreator dbProviderFactoryCreator)
+ public UmbracoDatabaseFactory(ILogger logger, IGlobalSettings globalSettings, IConnectionStrings connectionStrings, string connectionStringName, Lazy mappers, IDbProviderFactoryCreator dbProviderFactoryCreator)
{
if (connectionStringName == null) throw new ArgumentNullException(nameof(connectionStringName));
if (string.IsNullOrWhiteSpace(connectionStringName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(connectionStringName));
_globalSettings = globalSettings;
- _connectionStrings = connectionStrings;
_mappers = mappers ?? throw new ArgumentNullException(nameof(mappers));
_dbProviderFactoryCreator = dbProviderFactoryCreator ?? throw new ArgumentNullException(nameof(dbProviderFactoryCreator));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
@@ -118,7 +115,7 @@ namespace Umbraco.Core.Persistence
/// Initializes a new instance of the .
///
/// Used in tests.
- public UmbracoDatabaseFactory(string connectionString, string providerName, ILogger logger, Lazy mappers, IDbProviderFactoryCreator dbProviderFactoryCreator)
+ public UmbracoDatabaseFactory(ILogger logger, string connectionString, string providerName, Lazy mappers, IDbProviderFactoryCreator dbProviderFactoryCreator)
{
_mappers = mappers ?? throw new ArgumentNullException(nameof(mappers));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
@@ -142,7 +139,7 @@ namespace Umbraco.Core.Persistence
{
lock (_lock)
{
- return !_connectionString.IsNullOrWhiteSpace() && !_providerName.IsNullOrWhiteSpace();
+ return !ConnectionString.IsNullOrWhiteSpace() && !_providerName.IsNullOrWhiteSpace();
}
}
}
@@ -151,13 +148,13 @@ namespace Umbraco.Core.Persistence
public bool Initialized => Volatile.Read(ref _initialized);
///
- public string ConnectionString => _connectionString;
+ public string ConnectionString { get; private set; }
///
public bool CanConnect =>
// actually tries to connect to the database (regardless of configured/initialized)
- !_connectionString.IsNullOrWhiteSpace() && !_providerName.IsNullOrWhiteSpace() &&
- DbConnectionExtensions.IsConnectionAvailable(_connectionString, DbProviderFactory);
+ !ConnectionString.IsNullOrWhiteSpace() && !_providerName.IsNullOrWhiteSpace() &&
+ DbConnectionExtensions.IsConnectionAvailable(ConnectionString, DbProviderFactory);
private void UpdateSqlServerDatabaseType()
{
@@ -169,7 +166,7 @@ namespace Umbraco.Core.Persistence
if (setting.IsNullOrWhiteSpace() || !setting.StartsWith("SqlServer.")
|| !Enum.TryParse(setting.Substring("SqlServer.".Length), out var versionName, true))
{
- versionName = ((SqlServerSyntaxProvider) _sqlSyntax).GetSetVersion(_connectionString, _providerName, _logger).ProductVersionName;
+ versionName = ((SqlServerSyntaxProvider) _sqlSyntax).GetSetVersion(ConnectionString, _providerName, _logger).ProductVersionName;
}
else
{
@@ -233,7 +230,7 @@ namespace Umbraco.Core.Persistence
if (Volatile.Read(ref _initialized))
throw new InvalidOperationException("Already initialized.");
- _connectionString = connectionString;
+ ConnectionString = connectionString;
_providerName = providerName;
}
@@ -249,18 +246,19 @@ namespace Umbraco.Core.Persistence
{
_logger.Debug("Initializing.");
- if (_connectionString.IsNullOrWhiteSpace()) throw new InvalidOperationException("The factory has not been configured with a proper connection string.");
+ if (ConnectionString.IsNullOrWhiteSpace()) throw new InvalidOperationException("The factory has not been configured with a proper connection string.");
if (_providerName.IsNullOrWhiteSpace()) throw new InvalidOperationException("The factory has not been configured with a proper provider name.");
if (DbProviderFactory == null)
throw new Exception($"Can't find a provider factory for provider name \"{_providerName}\".");
// cannot initialize without being able to talk to the database
- if (!DbConnectionExtensions.IsConnectionAvailable(_connectionString, DbProviderFactory))
+ // TODO: Why not?
+ if (!DbConnectionExtensions.IsConnectionAvailable(ConnectionString, DbProviderFactory))
throw new Exception("Cannot connect to the database.");
- _connectionRetryPolicy = RetryPolicyFactory.GetDefaultSqlConnectionRetryPolicyByConnectionString(_connectionString);
- _commandRetryPolicy = RetryPolicyFactory.GetDefaultSqlCommandRetryPolicyByConnectionString(_connectionString);
+ _connectionRetryPolicy = RetryPolicyFactory.GetDefaultSqlConnectionRetryPolicyByConnectionString(ConnectionString);
+ _commandRetryPolicy = RetryPolicyFactory.GetDefaultSqlCommandRetryPolicyByConnectionString(ConnectionString);
_databaseType = DatabaseType.Resolve(DbProviderFactory.GetType().Name, _providerName);
@@ -313,7 +311,7 @@ namespace Umbraco.Core.Persistence
// method used by NPoco's UmbracoDatabaseFactory to actually create the database instance
private UmbracoDatabase CreateDatabaseInstance()
{
- return new UmbracoDatabase(_connectionString, SqlContext, DbProviderFactory, _logger, _bulkSqlInsertProvider, _connectionRetryPolicy, _commandRetryPolicy);
+ return new UmbracoDatabase(ConnectionString, SqlContext, DbProviderFactory, _logger, _bulkSqlInsertProvider, _connectionRetryPolicy, _commandRetryPolicy);
}
protected override void DisposeResources()
diff --git a/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs b/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs
index ec9a7d21db..85d915b433 100644
--- a/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs
+++ b/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs
@@ -33,14 +33,12 @@ namespace Umbraco.Core.Runtime
// unique id for our appdomain, this is more unique than the appdomain id which is just an INT counter to its safer
_lockId = Guid.NewGuid().ToString();
_logger = logger;
- _dbFactory = new UmbracoDatabaseFactory(
- Constants.System.UmbracoConnectionName,
+ _dbFactory = new UmbracoDatabaseFactory(_logger,
globalSettings,
connectionStrings,
- _logger,
+ Constants.System.UmbracoConnectionName,
new Lazy(() => new MapperCollection(Enumerable.Empty())),
- dbProviderFactoryCreator
- );
+ dbProviderFactoryCreator);
}
public async Task AcquireLockAsync(int millisecondsTimeout)
diff --git a/src/Umbraco.Tests.Common/Builders/UserBuilder.cs b/src/Umbraco.Tests.Common/Builders/UserBuilder.cs
new file mode 100644
index 0000000000..07ab8ef3f7
--- /dev/null
+++ b/src/Umbraco.Tests.Common/Builders/UserBuilder.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Linq;
+using Moq;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Models.Membership;
+using Umbraco.Tests.Common.Builders.Interfaces;
+
+namespace Umbraco.Tests.Common.Builders
+{
+ public class UserBuilder
+ : BuilderBase,
+ IWithIdBuilder
+ {
+ private int? _id;
+ private string _language;
+ private bool? _approved;
+ private string _name;
+ private string _rawPassword;
+ private bool? _isLockedOut;
+ private string _email;
+ private string _username;
+ private string _defaultLang;
+ private string _suffix = string.Empty;
+
+ public UserBuilder WithDefaultUILanguage(string defaultLang)
+ {
+ _defaultLang = defaultLang;
+ return this;
+ }
+
+ public UserBuilder WithLanguage(string language)
+ {
+ _language = language;
+ return this;
+ }
+
+ public UserBuilder WithApproved(bool approved)
+ {
+ _approved = approved;
+ return this;
+ }
+
+ public UserBuilder WithRawPassword(string rawPassword)
+ {
+ _rawPassword = rawPassword;
+ return this;
+ }
+
+ public UserBuilder WithEmail(string email)
+ {
+ _email = email;
+ return this;
+ }
+
+ public UserBuilder WithUsername(string username)
+ {
+ _username = username;
+ return this;
+ }
+
+ public UserBuilder WithLockedOut(bool isLockedOut)
+ {
+ _isLockedOut = isLockedOut;
+ return this;
+ }
+
+ public UserBuilder WithName(string name)
+ {
+ _name = name;
+ return this;
+ }
+
+ ///
+ /// Will suffix the name, email and username for testing
+ ///
+ ///
+ ///
+ public UserBuilder WithSuffix(string suffix)
+ {
+ _suffix = suffix;
+ return this;
+ }
+
+ public override User Build()
+ {
+ var globalSettings = Mock.Of(x => x.DefaultUILanguage == (_defaultLang ?? "en-US"));
+ return new User(globalSettings,
+ _name ?? "TestUser" + _suffix,
+ _email ?? "test" + _suffix + "@test.com",
+ _username ?? "TestUser" + _suffix,
+ _rawPassword ?? "abcdefghijklmnopqrstuvwxyz")
+ {
+ Language = _language ?? _defaultLang ?? "en-US",
+ IsLockedOut = _isLockedOut ?? false,
+ IsApproved = _approved ?? true
+ };
+ }
+
+ int? IWithIdBuilder.Id
+ {
+ get => _id;
+ set => _id = value;
+ }
+ }
+}
diff --git a/src/Umbraco.Tests.Common/Builders/UserGroupBuilder.cs b/src/Umbraco.Tests.Common/Builders/UserGroupBuilder.cs
new file mode 100644
index 0000000000..d3ce5e71a8
--- /dev/null
+++ b/src/Umbraco.Tests.Common/Builders/UserGroupBuilder.cs
@@ -0,0 +1,65 @@
+using System.Collections.Generic;
+using System.Linq;
+using Moq;
+using Umbraco.Core.Models.Membership;
+using Umbraco.Tests.Common.Builders.Interfaces;
+
+namespace Umbraco.Tests.Common.Builders
+{
+ public class UserGroupBuilder
+ : BuilderBase,
+ IWithIdBuilder
+ {
+ private int? _startContentId;
+ private int? _startMediaId;
+ private string _alias;
+ private string _icon;
+ private string _name;
+ private IEnumerable _permissions = Enumerable.Empty();
+ private IEnumerable _sectionCollection = Enumerable.Empty();
+ private string _suffix;
+ private int? _id;
+
+ ///
+ /// Will suffix the name and alias for testing
+ ///
+ ///
+ ///
+ public UserGroupBuilder WithSuffix(string suffix)
+ {
+ _suffix = suffix;
+ return this;
+ }
+
+ public IReadOnlyUserGroup BuildReadOnly(IUserGroup userGroup)
+ {
+ return Mock.Of(x =>
+ x.Permissions == userGroup.Permissions &&
+ x.Alias == userGroup.Alias &&
+ x.Icon == userGroup.Icon &&
+ x.Name == userGroup.Name &&
+ x.StartContentId == userGroup.StartContentId &&
+ x.StartMediaId == userGroup.StartMediaId &&
+ x.AllowedSections == userGroup.AllowedSections &&
+ x.Id == userGroup.Id);
+ }
+
+ public override IUserGroup Build()
+ {
+ return Mock.Of(x =>
+ x.StartContentId == _startContentId &&
+ x.StartMediaId == _startMediaId &&
+ x.Name == (_name ?? ("TestUserGroup" + _suffix)) &&
+ x.Alias == (_alias ?? ("testUserGroup" + _suffix)) &&
+ x.Icon == _icon &&
+ x.Permissions == _permissions &&
+ x.AllowedSections == _sectionCollection);
+ }
+
+ int? IWithIdBuilder.Id
+ {
+ get => _id;
+ set => _id = value;
+ }
+ }
+}
diff --git a/src/Umbraco.Tests/Testing/TestOptionAttributeBase.cs b/src/Umbraco.Tests.Common/Testing/TestOptionAttributeBase.cs
similarity index 88%
rename from src/Umbraco.Tests/Testing/TestOptionAttributeBase.cs
rename to src/Umbraco.Tests.Common/Testing/TestOptionAttributeBase.cs
index 2fb4660481..bbfa68778f 100644
--- a/src/Umbraco.Tests/Testing/TestOptionAttributeBase.cs
+++ b/src/Umbraco.Tests.Common/Testing/TestOptionAttributeBase.cs
@@ -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)
diff --git a/src/Umbraco.Tests/Testing/UmbracoTestAttribute.cs b/src/Umbraco.Tests.Common/Testing/UmbracoTestAttribute.cs
similarity index 100%
rename from src/Umbraco.Tests/Testing/UmbracoTestAttribute.cs
rename to src/Umbraco.Tests.Common/Testing/UmbracoTestAttribute.cs
diff --git a/src/Umbraco.Tests.Common/Testing/UmbracoTestOptions.cs b/src/Umbraco.Tests.Common/Testing/UmbracoTestOptions.cs
new file mode 100644
index 0000000000..eef6e45d7e
--- /dev/null
+++ b/src/Umbraco.Tests.Common/Testing/UmbracoTestOptions.cs
@@ -0,0 +1,61 @@
+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 fixture
+ ///
+ NewEmptyPerFixture,
+ ///
+ /// new empty database file per test
+ ///
+ NewEmptyPerTest,
+ ///
+ /// new database file with schema for the entire fixture
+ ///
+ 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
+ }
+ }
+}
diff --git a/src/Umbraco.Tests.Integration/ContainerTests.cs b/src/Umbraco.Tests.Integration/ContainerTests.cs
index 945eeda2f0..34a32a38a8 100644
--- a/src/Umbraco.Tests.Integration/ContainerTests.cs
+++ b/src/Umbraco.Tests.Integration/ContainerTests.cs
@@ -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;
diff --git a/src/Umbraco.Tests.Integration/Extensions/ApplicationBuilderExtensions.cs b/src/Umbraco.Tests.Integration/Extensions/ApplicationBuilderExtensions.cs
new file mode 100644
index 0000000000..553aa4fe85
--- /dev/null
+++ b/src/Umbraco.Tests.Integration/Extensions/ApplicationBuilderExtensions.cs
@@ -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
+ {
+ ///
+ /// Creates a LocalDb instance to use for the test
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IApplicationBuilder UseTestLocalDb(this IApplicationBuilder app,
+ string dbFilePath,
+ UmbracoIntegrationTest integrationTest)
+ {
+ // get the currently set db options
+ var testOptions = TestOptionAttributeBase.GetTestOptions();
+
+ 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(),
+ app.ApplicationServices.GetRequiredService(),
+ app.ApplicationServices.GetRequiredService());
+
+ 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();
+ 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();
+ Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level);
+
+ // dynamically change the config status
+ var umbVersion = app.ApplicationServices.GetRequiredService();
+ var config = app.ApplicationServices.GetRequiredService();
+ config[GlobalSettings.Prefix + "ConfigurationStatus"] = umbVersion.SemanticVersion.ToString();
+
+ // re-run the runtime level check
+ var profilingLogger = app.ApplicationServices.GetRequiredService();
+ 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;
+ }
+
+ }
+
+
+}
diff --git a/src/Umbraco.Tests.Integration/Extensions/ServiceCollectionExtensions.cs b/src/Umbraco.Tests.Integration/Extensions/ServiceCollectionExtensions.cs
new file mode 100644
index 0000000000..9dde20036b
--- /dev/null
+++ b/src/Umbraco.Tests.Integration/Extensions/ServiceCollectionExtensions.cs
@@ -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
+ {
+ ///
+ /// These services need to be manually added because they do not get added by the generic host
+ ///
+ ///
+ ///
+ ///
+ public static void AddRequiredNetCoreServices(this IServiceCollection services, TestHelper testHelper, IWebHostEnvironment webHostEnvironment)
+ {
+ services.AddSingleton(x => testHelper.GetHttpContextAccessor());
+ // the generic host does add IHostEnvironment but not this one because we are not actually in a web context
+ services.AddSingleton(x => webHostEnvironment);
+ }
+ }
+}
diff --git a/src/Umbraco.Tests.Integration/GlobalSetupTeardown.cs b/src/Umbraco.Tests.Integration/GlobalSetupTeardown.cs
new file mode 100644
index 0000000000..fe1d604dd9
--- /dev/null
+++ b/src/Umbraco.Tests.Integration/GlobalSetupTeardown.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+using NUnit.Framework;
+using Umbraco.Tests.Integration.Testing;
+
+// this class has NO NAMESPACE
+// it applies to the whole assembly
+
+[SetUpFixture]
+// ReSharper disable once CheckNamespace
+public class TestsSetup
+{
+ private Stopwatch _stopwatch;
+
+ [OneTimeSetUp]
+ public void SetUp()
+ {
+ _stopwatch = Stopwatch.StartNew();
+ }
+
+ [OneTimeTearDown]
+ public void TearDown()
+ {
+ LocalDbTestDatabase.KillLocalDb();
+ Console.WriteLine("TOTAL TESTS DURATION: {0}", _stopwatch.Elapsed);
+ }
+}
diff --git a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs
deleted file mode 100644
index 60cac26349..0000000000
--- a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Data.Common;
-using System.Data.SqlClient;
-using System.IO;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.Hosting;
-using Umbraco.Core;
-using Umbraco.Tests.Integration.Testing;
-
-namespace Umbraco.Tests.Integration.Implementations
-{
- public static class HostBuilderExtensions
- {
-
- public static IHostBuilder UseLocalDb(this IHostBuilder hostBuilder, string dbFilePath)
- {
- // Need to register SqlClient manually
- // TODO: Move this to someplace central
- DbProviderFactories.RegisterFactory(Constants.DbProviderNames.SqlServer, SqlClientFactory.Instance);
-
- hostBuilder.ConfigureAppConfiguration(x =>
- {
- if (!Directory.Exists(dbFilePath))
- Directory.CreateDirectory(dbFilePath);
-
- var dbName = Guid.NewGuid().ToString("N");
- var instance = TestLocalDb.EnsureLocalDbInstanceAndDatabase(dbName, dbFilePath);
-
- x.AddInMemoryCollection(new[]
- {
- new KeyValuePair($"ConnectionStrings:{Constants.System.UmbracoConnectionName}", instance.GetConnectionString(dbName))
- });
- });
- return hostBuilder;
- }
-
-
- }
-
-
-}
diff --git a/src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/AuditRepositoryTest.cs
similarity index 72%
rename from src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs
rename to src/Umbraco.Tests.Integration/Persistence/Repositories/AuditRepositoryTest.cs
index 49e48e0a2f..e92653fb98 100644
--- a/src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs
+++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/AuditRepositoryTest.cs
@@ -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("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(), 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(), 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(), 0, 8, out var total, Direction.Descending,
null, sp.SqlContext.Query().Where(item => item.Comment == "Content created"))
diff --git a/src/Umbraco.Tests.Integration/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/UserRepositoryTest.cs
new file mode 100644
index 0000000000..7feb69f0c6
--- /dev/null
+++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/UserRepositoryTest.cs
@@ -0,0 +1,393 @@
+using System.Linq;
+using Moq;
+using NUnit.Framework;
+using Umbraco.Core;
+using Umbraco.Core.Cache;
+using Umbraco.Core.Logging;
+using Umbraco.Core.Models.Membership;
+using Umbraco.Core.Persistence.Mappers;
+using Umbraco.Core.Persistence.Repositories;
+using Umbraco.Core.Persistence.Repositories.Implement;
+using Umbraco.Core.Scoping;
+using Umbraco.Tests.Testing;
+using Umbraco.Core.Persistence;
+using Umbraco.Core.PropertyEditors;
+using System;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Services.Implement;
+using Umbraco.Tests.Integration.Testing;
+
+namespace Umbraco.Tests.Persistence.Repositories
+{
+ [TestFixture]
+ [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, WithApplication = true, Logger = UmbracoTestOptions.Logger.Console)]
+ public class UserRepositoryTest : UmbracoIntegrationTest
+ {
+ private UserRepository CreateRepository(IScopeProvider provider)
+ {
+ var accessor = (IScopeAccessor) provider;
+ var repository = new UserRepository(accessor, AppCaches.Disabled, Logger, Mappers, GlobalSettings, Mock.Of());
+ return repository;
+ }
+
+ private UserGroupRepository CreateUserGroupRepository(IScopeProvider provider)
+ {
+ var accessor = (IScopeAccessor) provider;
+ return new UserGroupRepository(accessor, AppCaches.Disabled, Logger, ShortStringHelper);
+ }
+
+ [Test]
+ public void Can_Perform_Add_On_UserRepository()
+ {
+ // Arrange
+ var provider = ScopeProvider;
+ using (var scope = provider.CreateScope())
+ {
+ var repository = CreateRepository(provider);
+
+ var user = UserBuilder.Build();
+
+ // Act
+ repository.Save(user);
+
+
+ // Assert
+ Assert.That(user.HasIdentity, Is.True);
+ }
+ }
+
+ [Test]
+ public void Can_Perform_Multiple_Adds_On_UserRepository()
+ {
+ // Arrange
+ var provider = ScopeProvider;
+ using (var scope = provider.CreateScope())
+ {
+ var repository = CreateRepository(provider);
+
+ var user1 = UserBuilder.WithSuffix("1").Build();
+ var use2 = UserBuilder.WithSuffix("2").Build();
+
+ // Act
+ repository.Save(user1);
+
+ repository.Save(use2);
+
+
+ // Assert
+ Assert.That(user1.HasIdentity, Is.True);
+ Assert.That(use2.HasIdentity, Is.True);
+ }
+ }
+
+ [Test]
+ public void Can_Verify_Fresh_Entity_Is_Not_Dirty()
+ {
+ // Arrange
+ var provider = ScopeProvider;
+ using (var scope = provider.CreateScope())
+ {
+ var repository = CreateRepository(provider);
+
+ var user = UserBuilder.Build();
+ repository.Save(user);
+
+
+ // Act
+ var resolved = repository.Get((int)user.Id);
+ bool dirty = ((User)resolved).IsDirty();
+
+ // Assert
+ Assert.That(dirty, Is.False);
+ }
+ }
+
+ [Test]
+ public void Can_Perform_Delete_On_UserRepository()
+ {
+ // Arrange
+ var provider = ScopeProvider;
+ using (var scope = provider.CreateScope())
+ {
+ var repository = CreateRepository(provider);
+
+ var user = UserBuilder.Build();
+
+ // Act
+ repository.Save(user);
+
+ var id = user.Id;
+
+ var repository2 = new UserRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, Mock.Of(),GlobalSettings, Mock.Of());
+
+ repository2.Delete(user);
+
+
+ var resolved = repository2.Get((int) id);
+
+ // Assert
+ Assert.That(resolved, Is.Null);
+ }
+ }
+
+ [Test]
+ public void Can_Perform_Get_On_UserRepository()
+ {
+ // Arrange
+ var provider = ScopeProvider;
+ using (var scope = provider.CreateScope())
+ {
+ var repository = CreateRepository(provider);
+ var userGroupRepository = CreateUserGroupRepository(provider);
+
+ var user = CreateAndCommitUserWithGroup(repository, userGroupRepository);
+
+ // Act
+ var updatedItem = repository.Get(user.Id);
+
+ // FIXME: this test cannot work, user has 2 sections but the way it's created,
+ // they don't show, so the comparison with updatedItem fails - fix!
+
+ // Assert
+ AssertPropertyValues(updatedItem, user);
+ }
+ }
+
+ [Test]
+ public void Can_Perform_GetByQuery_On_UserRepository()
+ {
+ // Arrange
+ var provider = ScopeProvider;
+ using (var scope = provider.CreateScope())
+ {
+ var repository = CreateRepository(provider);
+
+ CreateAndCommitMultipleUsers(repository);
+
+ // Act
+ var query = scope.SqlContext.Query().Where(x => x.Username == "TestUser1");
+ var result = repository.Get(query);
+
+ // Assert
+ Assert.That(result.Count(), Is.GreaterThanOrEqualTo(1));
+ }
+ }
+
+ [Test]
+ public void Can_Perform_GetAll_By_Param_Ids_On_UserRepository()
+ {
+ // Arrange
+ var provider = ScopeProvider;
+ using (var scope = provider.CreateScope())
+ {
+ var repository = CreateRepository(provider);
+
+ var users = CreateAndCommitMultipleUsers(repository);
+
+ // Act
+ var result = repository.GetMany((int) users[0].Id, (int) users[1].Id);
+
+ // Assert
+ Assert.That(result, Is.Not.Null);
+ Assert.That(result.Any(), Is.True);
+ Assert.That(result.Count(), Is.EqualTo(2));
+ }
+ }
+
+ [Test]
+ public void Can_Perform_GetAll_On_UserRepository()
+ {
+ // Arrange
+ var provider = ScopeProvider;
+ using (var scope = provider.CreateScope())
+ {
+ var repository = CreateRepository(provider);
+
+ CreateAndCommitMultipleUsers(repository);
+
+ // Act
+ var result = repository.GetMany();
+
+ // Assert
+ Assert.That(result, Is.Not.Null);
+ Assert.That(result.Any(), Is.True);
+ Assert.That(result.Count(), Is.GreaterThanOrEqualTo(3));
+ }
+ }
+
+ [Test]
+ public void Can_Perform_Exists_On_UserRepository()
+ {
+ // Arrange
+ var provider = ScopeProvider;
+ using (var scope = provider.CreateScope())
+ {
+ var repository = CreateRepository(provider);
+
+ var users = CreateAndCommitMultipleUsers(repository);
+
+ // Act
+ var exists = repository.Exists(users[0].Id);
+
+ // Assert
+ Assert.That(exists, Is.True);
+ }
+ }
+
+ [Test]
+ public void Can_Perform_Count_On_UserRepository()
+ {
+ // Arrange
+ var provider = ScopeProvider;
+ using (var scope = provider.CreateScope())
+ {
+ var repository = CreateRepository(provider);
+
+ var users = CreateAndCommitMultipleUsers(repository);
+
+ // Act
+ var query = scope.SqlContext.Query().Where(x => x.Username == "TestUser1" || x.Username == "TestUser2");
+ var result = repository.Count(query);
+
+ // Assert
+ Assert.AreEqual(2, result);
+ }
+ }
+
+ [Test]
+ public void Can_Get_Paged_Results_By_Query_And_Filter_And_Groups()
+ {
+ var provider = ScopeProvider;
+ using (var scope = provider.CreateScope())
+ {
+ var repository = CreateRepository(provider);
+
+ var users = CreateAndCommitMultipleUsers(repository);
+ var query = provider.SqlContext.Query().Where(x => x.Username == "TestUser1" || x.Username == "TestUser2");
+
+ try
+ {
+ scope.Database.AsUmbracoDatabase().EnableSqlTrace = true;
+ scope.Database.AsUmbracoDatabase().EnableSqlCount = true;
+
+ // Act
+ var result = repository.GetPagedResultsByQuery(query, 0, 10, out var totalRecs, user => user.Id, Direction.Ascending,
+ excludeUserGroups: new[] { Constants.Security.TranslatorGroupAlias },
+ filter: provider.SqlContext.Query().Where(x => x.Id > -1));
+
+ // Assert
+ Assert.AreEqual(2, totalRecs);
+ }
+ finally
+ {
+ scope.Database.AsUmbracoDatabase().EnableSqlTrace = false;
+ scope.Database.AsUmbracoDatabase().EnableSqlCount = false;
+ }
+ }
+
+ }
+
+ [Test]
+ public void Can_Get_Paged_Results_With_Filter_And_Groups()
+ {
+ var provider = ScopeProvider;
+ using (var scope = provider.CreateScope())
+ {
+ var repository = CreateRepository(provider);
+
+ var users = CreateAndCommitMultipleUsers(repository);
+
+ try
+ {
+ scope.Database.AsUmbracoDatabase().EnableSqlTrace = true;
+ scope.Database.AsUmbracoDatabase().EnableSqlCount = true;
+
+ // Act
+ var result = repository.GetPagedResultsByQuery(null, 0, 10, out var totalRecs, user => user.Id, Direction.Ascending,
+ includeUserGroups: new[] { Constants.Security.AdminGroupAlias, Constants.Security.SensitiveDataGroupAlias },
+ excludeUserGroups: new[] { Constants.Security.TranslatorGroupAlias },
+ filter: provider.SqlContext.Query().Where(x => x.Id == -1));
+
+ // Assert
+ Assert.AreEqual(1, totalRecs);
+ }
+ finally
+ {
+ scope.Database.AsUmbracoDatabase().EnableSqlTrace = false;
+ scope.Database.AsUmbracoDatabase().EnableSqlCount = false;
+ }
+ }
+ }
+
+ [Test]
+ public void Can_Invalidate_SecurityStamp_On_Username_Change()
+ {
+ // Arrange
+ var provider = ScopeProvider;
+ using (var scope = provider.CreateScope())
+ {
+ var repository = CreateRepository(provider);
+ var userGroupRepository = CreateUserGroupRepository(provider);
+
+ var user = CreateAndCommitUserWithGroup(repository, userGroupRepository);
+ var originalSecurityStamp = user.SecurityStamp;
+
+ // Ensure when user generated a security stamp is present
+ Assert.That(user.SecurityStamp, Is.Not.Null);
+ Assert.That(user.SecurityStamp, Is.Not.Empty);
+
+ // Update username
+ user.Username = user.Username + "UPDATED";
+ repository.Save(user);
+
+ // Get the user
+ var updatedUser = repository.Get(user.Id);
+
+ // Ensure the Security Stamp is invalidated & no longer the same
+ Assert.AreNotEqual(originalSecurityStamp, updatedUser.SecurityStamp);
+ }
+ }
+
+ private void AssertPropertyValues(IUser updatedItem, IUser originalUser)
+ {
+ Assert.That(updatedItem.Id, Is.EqualTo(originalUser.Id));
+ Assert.That(updatedItem.Name, Is.EqualTo(originalUser.Name));
+ Assert.That(updatedItem.Language, Is.EqualTo(originalUser.Language));
+ Assert.That(updatedItem.IsApproved, Is.EqualTo(originalUser.IsApproved));
+ Assert.That(updatedItem.RawPasswordValue, Is.EqualTo(originalUser.RawPasswordValue));
+ Assert.That(updatedItem.IsLockedOut, Is.EqualTo(originalUser.IsLockedOut));
+ Assert.IsTrue(updatedItem.StartContentIds.UnsortedSequenceEqual(originalUser.StartContentIds));
+ Assert.IsTrue(updatedItem.StartMediaIds.UnsortedSequenceEqual(originalUser.StartMediaIds));
+ Assert.That(updatedItem.Email, Is.EqualTo(originalUser.Email));
+ Assert.That(updatedItem.Username, Is.EqualTo(originalUser.Username));
+ Assert.That(updatedItem.AllowedSections.Count(), Is.EqualTo(originalUser.AllowedSections.Count()));
+ foreach (var allowedSection in originalUser.AllowedSections)
+ Assert.IsTrue(updatedItem.AllowedSections.Contains(allowedSection));
+ }
+
+ private User CreateAndCommitUserWithGroup(IUserRepository repository, IUserGroupRepository userGroupRepository)
+ {
+ var user = UserBuilder.Build();
+ repository.Save(user);
+
+
+ var group = UserGroupBuilder.Build();
+ userGroupRepository.AddOrUpdateGroupWithUsers(@group, new[] { user.Id });
+
+ user.AddGroup(UserGroupBuilder.BuildReadOnly(group));
+
+ return user;
+ }
+
+ private IUser[] CreateAndCommitMultipleUsers(IUserRepository repository)
+ {
+ var user1 = UserBuilder.WithSuffix("1").Build();
+ var user2 = UserBuilder.WithSuffix("2").Build();
+ var user3 = UserBuilder.WithSuffix("3").Build();
+ repository.Save(user1);
+ repository.Save(user2);
+ repository.Save(user3);
+ return new IUser[] { user1, user2, user3 };
+ }
+ }
+}
diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs
index 0e11a29b95..210f767de1 100644
--- a/src/Umbraco.Tests.Integration/RuntimeTests.cs
+++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs
@@ -1,28 +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.Core;
using Umbraco.Core.Composing;
-using Umbraco.Core.Composing.LightInject;
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
{
@@ -37,10 +30,11 @@ namespace Umbraco.Tests.Integration
MyComposer.Reset();
}
- [OneTimeTearDown]
- public void FixtureTearDown()
+ [SetUp]
+ public void Setup()
{
- TestLocalDb.Cleanup();
+ MyComponent.Reset();
+ MyComposer.Reset();
}
///
@@ -93,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()
@@ -101,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);
@@ -132,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()
@@ -140,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);
@@ -167,71 +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()
- //TODO: Need to have a configured umb version for the runtime state
- .UseLocalDb(Path.Combine(testHelper.CurrentAssemblyDirectory, "LocalDb"))
- .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);
-
- app.UseUmbracoCore();
-
-
- var runtimeState = (RuntimeState)app.ApplicationServices.GetRequiredService();
- Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level);
-
- var dbBuilder = app.ApplicationServices.GetRequiredService();
- Assert.IsNotNull(dbBuilder);
-
- var canConnect = dbBuilder.CanConnectToDatabase;
- Assert.IsTrue(canConnect);
-
- var dbResult = dbBuilder.CreateSchemaAndData();
- Assert.IsTrue(dbResult.Success);
-
- // TODO: Get this to work ... but to do that we need to mock or pass in a current umbraco version
- //var dbFactory = app.ApplicationServices.GetRequiredService();
- //var profilingLogger = app.ApplicationServices.GetRequiredService();
- //runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger);
- //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;
- }
-
- ///
- /// These services need to be manually added because they do not get added by the generic host
- ///
- ///
- ///
- ///
- private void AddRequiredNetCoreServices(IServiceCollection services, TestHelper testHelper, IWebHostEnvironment webHostEnvironment)
- {
- services.AddSingleton(x => testHelper.GetHttpContextAccessor());
- // the generic host does add IHostEnvironment but not this one because we are not actually in a web context
- services.AddSingleton(x => webHostEnvironment);
- }
[RuntimeLevel(MinLevel = RuntimeLevel.Install)]
public class MyComposer : IUserComposer
diff --git a/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs
new file mode 100644
index 0000000000..da2b83bc39
--- /dev/null
+++ b/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs
@@ -0,0 +1,326 @@
+using System;
+using System.Collections.Concurrent;
+using System.Configuration;
+using System.Data;
+using System.Data.Common;
+using System.Data.SqlClient;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Logging;
+using Umbraco.Core.Migrations.Install;
+using Umbraco.Core.Persistence;
+
+namespace Umbraco.Tests.Integration.Testing
+{
+ ///
+ /// Manages a pool of LocalDb databases for integration testing
+ ///
+ public class LocalDbTestDatabase
+ {
+ public const string InstanceName = "UmbracoTests";
+ public const string DatabaseName = "UmbracoTests";
+
+ private readonly ILogger _logger;
+ private readonly IGlobalSettings _globalSettings;
+ private readonly LocalDb _localDb;
+ private readonly IUmbracoVersion _umbracoVersion;
+ private static LocalDb.Instance _instance;
+ private static string _filesPath;
+ private readonly IUmbracoDatabaseFactory _dbFactory;
+ private UmbracoDatabase.CommandInfo[] _dbCommands;
+ private string _currentCstr;
+ private static DatabasePool _emptyPool;
+ private static DatabasePool _schemaPool;
+ private DatabasePool _currentPool;
+
+ //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;
+ _globalSettings = globalSettings;
+ _localDb = localDb;
+ _filesPath = filesPath;
+ _dbFactory = dbFactory;
+
+ _instance = _localDb.GetInstance(InstanceName);
+ if (_instance != null) return;
+
+ if (_localDb.CreateInstance(InstanceName) == false)
+ throw new Exception("Failed to create a LocalDb instance.");
+ _instance = _localDb.GetInstance(InstanceName);
+ }
+
+ public string ConnectionString => _currentCstr ?? _instance.GetAttachedConnectionString("XXXXXX", _filesPath);
+
+ private void Create()
+ {
+ var tempName = Guid.NewGuid().ToString("N");
+ _instance.CreateDatabase(tempName, _filesPath);
+ _instance.DetachDatabase(tempName);
+
+ // there's probably a sweet spot to be found for size / parallel...
+
+ var s = ConfigurationManager.AppSettings["Umbraco.Tests.LocalDbTestDatabase.EmptyPoolSize"];
+ var emptySize = s == null ? 2 : int.Parse(s);
+ s = ConfigurationManager.AppSettings["Umbraco.Tests.LocalDbTestDatabase.EmptyPoolThreadCount"];
+ var emptyParallel = s == null ? 1 : int.Parse(s);
+ s = ConfigurationManager.AppSettings["Umbraco.Tests.LocalDbTestDatabase.SchemaPoolSize"];
+ var schemaSize = s == null ? 2 : int.Parse(s);
+ s = ConfigurationManager.AppSettings["Umbraco.Tests.LocalDbTestDatabase.SchemaPoolThreadCount"];
+ var schemaParallel = s == null ? 1 : int.Parse(s);
+
+ _emptyPool = new DatabasePool(_localDb, _instance, DatabaseName + "-Empty", tempName, _filesPath, emptySize, emptyParallel);
+ _schemaPool = new DatabasePool(_localDb, _instance, DatabaseName + "-Schema", tempName, _filesPath, schemaSize, schemaParallel, delete: true, prepare: RebuildSchema);
+ }
+
+ public void AttachEmpty()
+ {
+ if (_emptyPool == null)
+ Create();
+
+ _currentCstr = _emptyPool.AttachDatabase();
+ _currentPool = _emptyPool;
+ }
+
+ public void AttachSchema()
+ {
+ if (_schemaPool == null)
+ Create();
+
+ _currentCstr = _schemaPool.AttachDatabase();
+ _currentPool = _schemaPool;
+ }
+
+ public void Detach()
+ {
+ _currentPool.DetachDatabase();
+ }
+
+ private void RebuildSchema(DbConnection conn, IDbCommand cmd)
+ {
+
+ if (_dbCommands != null)
+ {
+ foreach (var dbCommand in _dbCommands)
+ {
+
+ if (dbCommand.Text.StartsWith("SELECT ")) continue;
+
+ cmd.CommandText = dbCommand.Text;
+ cmd.Parameters.Clear();
+ foreach (var parameterInfo in dbCommand.Parameters)
+ AddParameter(cmd, parameterInfo);
+ cmd.ExecuteNonQuery();
+ }
+ }
+ else
+ {
+ _dbFactory.Configure(conn.ConnectionString, Umbraco.Core.Constants.DatabaseProviders.SqlServer);
+
+ using var database = (UmbracoDatabase)_dbFactory.CreateDatabase();
+ // track each db command ran as part of creating the database so we can replay these
+ database.LogCommands = true;
+
+ using var trans = database.GetTransaction();
+
+ var creator = new DatabaseSchemaCreator(database, _logger, _umbracoVersion, _globalSettings);
+ creator.InitializeDatabaseSchema();
+
+ trans.Complete(); // commit it
+
+ _dbCommands = database.Commands.ToArray();
+ }
+
+ }
+
+ private static void AddParameter(IDbCommand cmd, UmbracoDatabase.ParameterInfo parameterInfo)
+ {
+ var p = cmd.CreateParameter();
+ p.ParameterName = parameterInfo.Name;
+ p.Value = parameterInfo.Value;
+ p.DbType = parameterInfo.DbType;
+ p.Size = parameterInfo.Size;
+ cmd.Parameters.Add(p);
+ }
+
+ public void Clear()
+ {
+ var filename = Path.Combine(_filesPath, DatabaseName).ToUpper();
+
+ foreach (var database in _instance.GetDatabases())
+ {
+ if (database.StartsWith(filename))
+ _instance.DropDatabase(database);
+ }
+
+ foreach (var file in Directory.EnumerateFiles(_filesPath))
+ {
+ if (file.EndsWith(".mdf") == false && file.EndsWith(".ldf") == false) continue;
+ File.Delete(file);
+ }
+ }
+
+ private static void ResetLocalDb(IDbCommand cmd)
+ {
+ // https://stackoverflow.com/questions/536350
+
+ cmd.CommandType = CommandType.Text;
+ cmd.CommandText = @"
+ declare @n char(1);
+ set @n = char(10);
+ declare @stmt nvarchar(max);
+ -- check constraints
+ select @stmt = isnull( @stmt + @n, '' ) +
+ 'alter table [' + schema_name(schema_id) + '].[' + object_name( parent_object_id ) + '] drop constraint [' + name + ']'
+ from sys.check_constraints;
+ -- foreign keys
+ select @stmt = isnull( @stmt + @n, '' ) +
+ 'alter table [' + schema_name(schema_id) + '].[' + object_name( parent_object_id ) + '] drop constraint [' + name + ']'
+ from sys.foreign_keys;
+ -- tables
+ select @stmt = isnull( @stmt + @n, '' ) +
+ 'drop table [' + schema_name(schema_id) + '].[' + name + ']'
+ from sys.tables;
+ exec sp_executesql @stmt;
+ ";
+ cmd.ExecuteNonQuery();
+ }
+
+ public static void KillLocalDb()
+ {
+ _emptyPool?.Stop();
+ _schemaPool?.Stop();
+
+ if (_filesPath == null)
+ return;
+
+ var filename = Path.Combine(_filesPath, DatabaseName).ToUpper();
+
+ foreach (var database in _instance.GetDatabases())
+ {
+ if (database.StartsWith(filename))
+ _instance.DropDatabase(database);
+ }
+
+ foreach (var file in Directory.EnumerateFiles(_filesPath))
+ {
+ if (file.EndsWith(".mdf") == false && file.EndsWith(".ldf") == false) continue;
+ try
+ {
+ File.Delete(file);
+ }
+ catch (IOException)
+ {
+ // ignore, must still be in use but nothing we can do
+ }
+ }
+ }
+
+ private class DatabasePool
+ {
+ private readonly LocalDb _localDb;
+ private readonly LocalDb.Instance _instance;
+ private readonly string _filesPath;
+ private readonly string _name;
+ private readonly int _size;
+ private readonly string[] _cstrs;
+ private readonly BlockingCollection _prepareQueue, _readyQueue;
+ private readonly Action _prepare;
+ private int _current;
+
+ public DatabasePool(LocalDb localDb, LocalDb.Instance instance, string name, string tempName, string filesPath, int size, int parallel = 1, Action prepare = null, bool delete = false)
+ {
+ _localDb = localDb;
+ _instance = instance;
+ _filesPath = filesPath;
+ _name = name;
+ _size = size;
+ _prepare = prepare;
+ _prepareQueue = new BlockingCollection();
+ _readyQueue = new BlockingCollection();
+ _cstrs = new string[_size];
+
+ for (var i = 0; i < size; i++)
+ localDb.CopyDatabaseFiles(tempName, filesPath, targetDatabaseName: name + "-" + i, overwrite: true, delete: delete && i == size - 1);
+
+ if (prepare == null)
+ {
+ for (var i = 0; i < size; i++)
+ _readyQueue.Add(i);
+ }
+ else
+ {
+ for (var i = 0; i < size; i++)
+ _prepareQueue.Add(i);
+ }
+
+ for (var i = 0; i < parallel; i++)
+ {
+ var thread = new Thread(PrepareThread);
+ thread.Start();
+ }
+ }
+
+ public string AttachDatabase()
+ {
+ try
+ {
+ _current = _readyQueue.Take();
+ }
+ catch (InvalidOperationException)
+ {
+ _current = 0;
+ return null;
+ }
+ return ConnectionString(_current);
+ }
+
+ public void DetachDatabase()
+ {
+ _prepareQueue.Add(_current);
+ }
+
+ private string ConnectionString(int i)
+ {
+ return _cstrs[i] ?? (_cstrs[i] = _instance.GetAttachedConnectionString(_name + "-" + i, _filesPath));
+ }
+
+ private void PrepareThread()
+ {
+ while (_prepareQueue.IsCompleted == false)
+ {
+ int i;
+ try
+ {
+ i = _prepareQueue.Take();
+ }
+ catch (InvalidOperationException)
+ {
+ continue;
+ }
+ using (var conn = new SqlConnection(ConnectionString(i)))
+ using (var cmd = conn.CreateCommand())
+ {
+ conn.Open();
+ ResetLocalDb(cmd);
+ _prepare?.Invoke(conn, cmd);
+ }
+ _readyQueue.Add(i);
+ }
+ }
+
+ public void Stop()
+ {
+ int i;
+ _prepareQueue.CompleteAdding();
+ while (_prepareQueue.TryTake(out i)) { }
+ _readyQueue.CompleteAdding();
+ while (_readyQueue.TryTake(out i)) { }
+ }
+ }
+
+ }
+}
diff --git a/src/Umbraco.Tests.Integration/Testing/TestLocalDb.cs b/src/Umbraco.Tests.Integration/Testing/TestLocalDb.cs
deleted file mode 100644
index 8ee326783b..0000000000
--- a/src/Umbraco.Tests.Integration/Testing/TestLocalDb.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using Umbraco.Core.Persistence;
-
-namespace Umbraco.Tests.Integration.Testing
-{
- public static class TestLocalDb
- {
- private const string LocalDbInstanceName = "UmbTests";
-
- private static LocalDb LocalDb { get; } = new LocalDb();
-
- // TODO: We need to borrow logic from this old branch, this is the latest commit at the old branch where we had LocalDb
- // working for tests. There's a lot of hoops to jump through to make it work 'fast'. Turns out it didn't actually run as
- // fast as SqlCe due to the dropping/creating of DB instances since that is faster in SqlCe but this code was all heavily
- // optimized to go as fast as possible.
- // see https://github.com/umbraco/Umbraco-CMS/blob/3a8716ac7b1c48b51258724337086cd0712625a1/src/Umbraco.Tests/TestHelpers/LocalDbTestDatabase.cs
- internal static LocalDb.Instance EnsureLocalDbInstanceAndDatabase(string dbName, string dbFilePath)
- {
- if (!LocalDb.InstanceExists(LocalDbInstanceName) && !LocalDb.CreateInstance(LocalDbInstanceName))
- {
- throw new InvalidOperationException(
- $"Failed to create LocalDb instance {LocalDbInstanceName}, assuming LocalDb is not really available.");
- }
-
- var instance = LocalDb.GetInstance(LocalDbInstanceName);
-
- if (instance == null)
- {
- throw new InvalidOperationException(
- $"Failed to get LocalDb instance {LocalDbInstanceName}, assuming LocalDb is not really available.");
- }
-
- instance.CreateDatabase(dbName, dbFilePath);
-
- return instance;
- }
-
- public static void Cleanup()
- {
- var instance = LocalDb.GetInstance(LocalDbInstanceName);
- if (instance != null)
- {
- instance.DropDatabases();
- }
- }
- }
-}
diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs
new file mode 100644
index 0000000000..3d94e52860
--- /dev/null
+++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs
@@ -0,0 +1,173 @@
+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.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.Tests.Testing;
+using Umbraco.Web.BackOffice.AspNetCore;
+
+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 GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory)
+ {
+ var container = UmbracoServiceProviderFactory.CreateServiceContainer();
+ serviceProviderFactory = new UmbracoServiceProviderFactory(container);
+ var umbracoContainer = serviceProviderFactory.GetContainer();
+ return umbracoContainer;
+ }
+
+ ///
+ /// Get or create an instance of
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// There must only be ONE instance shared between all tests in a session
+ ///
+ 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 _testTeardown = new List();
+ private readonly List _fixtureTeardown = new List();
+
+ 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();
+ }
+
+ #region Common services
+
+ ///
+ /// Returns the DI container
+ ///
+ protected IServiceProvider Services { get; private set; }
+
+ ///
+ /// Returns the
+ ///
+ protected IScopeProvider ScopeProvider => Services.GetRequiredService();
+
+ ///
+ /// Returns the
+ ///
+ protected IScopeAccessor ScopeAccessor => Services.GetRequiredService();
+
+ ///
+ /// Returns the
+ ///
+ protected ILogger Logger => Services.GetRequiredService();
+
+ protected AppCaches AppCaches => Services.GetRequiredService();
+ protected IIOHelper IOHelper => Services.GetRequiredService();
+ protected IShortStringHelper ShortStringHelper => Services.GetRequiredService();
+ protected IGlobalSettings GlobalSettings => Services.GetRequiredService();
+ protected IMapperCollection Mappers => Services.GetRequiredService();
+
+ #endregion
+
+ #region Builders
+
+ protected GlobalSettingsBuilder GlobalSettingsBuilder = new GlobalSettingsBuilder();
+ protected UserBuilder UserBuilder = new UserBuilder();
+ protected UserGroupBuilder UserGroupBuilder = new UserGroupBuilder();
+
+ #endregion
+ }
+}
diff --git a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs
index 52f2365cbc..d964ab972b 100644
--- a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs
+++ b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs
@@ -72,7 +72,7 @@ namespace Umbraco.Tests.Persistence
}
// re-create the database factory and database context with proper connection string
- _databaseFactory = new UmbracoDatabaseFactory(connString, Constants.DbProviderNames.SqlCe, _logger, new Lazy(() => Mock.Of()), TestHelper.DbProviderFactoryCreator);
+ _databaseFactory = new UmbracoDatabaseFactory(_logger, connString, Constants.DbProviderNames.SqlCe, new Lazy(() => Mock.Of()), TestHelper.DbProviderFactoryCreator);
// test get database type (requires an actual database)
using (var database = _databaseFactory.CreateDatabase())
diff --git a/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs b/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs
index 4a9e8e2b26..bab0617ec6 100644
--- a/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs
+++ b/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs
@@ -20,7 +20,7 @@ namespace Umbraco.Tests.Persistence.FaultHandling
{
const string connectionString = @"server=.\SQLEXPRESS;database=EmptyForTest;user id=x;password=umbraco";
const string providerName = Constants.DbProviderNames.SqlServer;
- var factory = new UmbracoDatabaseFactory(connectionString, providerName, Mock.Of(), new Lazy(() => Mock.Of()), TestHelper.DbProviderFactoryCreator);
+ var factory = new UmbracoDatabaseFactory(Mock.Of(), connectionString, providerName, new Lazy(() => Mock.Of()), TestHelper.DbProviderFactoryCreator);
using (var database = factory.CreateDatabase())
{
@@ -34,7 +34,7 @@ namespace Umbraco.Tests.Persistence.FaultHandling
{
const string connectionString = @"server=.\SQLEXPRESS;database=EmptyForTest;user id=umbraco;password=umbraco";
const string providerName = Constants.DbProviderNames.SqlServer;
- var factory = new UmbracoDatabaseFactory(connectionString, providerName, Mock.Of(), new Lazy(() => Mock.Of()), TestHelper.DbProviderFactoryCreator);
+ var factory = new UmbracoDatabaseFactory(Mock.Of(), connectionString, providerName, new Lazy(() => Mock.Of()), TestHelper.DbProviderFactoryCreator);
using (var database = factory.CreateDatabase())
{
diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs
index 201b84f29a..8938a69579 100644
--- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs
+++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs
@@ -5,21 +5,20 @@ using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Membership;
-using Umbraco.Core.Persistence.Mappers;
-using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.Repositories.Implement;
using Umbraco.Core.Scoping;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Entities;
using Umbraco.Tests.Testing;
-using Umbraco.Core.Persistence;
using Umbraco.Core.PropertyEditors;
using System;
using Umbraco.Core.Configuration;
namespace Umbraco.Tests.Persistence.Repositories
{
+ // TODO: Move the remaining parts to Integration tests
+
[TestFixture]
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, WithApplication = true, Logger = UmbracoTestOptions.Logger.Console)]
public class UserRepositoryTest : TestWithDatabaseBase
@@ -78,72 +77,6 @@ namespace Umbraco.Tests.Persistence.Repositories
return new UserGroupRepository(accessor, AppCaches.Disabled, Logger, ShortStringHelper);
}
- [Test]
- public void Can_Perform_Add_On_UserRepository()
- {
- // Arrange
- var provider = TestObjects.GetScopeProvider(Logger);
- using (var scope = provider.CreateScope())
- {
- var repository = CreateRepository(provider);
-
- var user = MockedUser.CreateUser();
-
- // Act
- repository.Save(user);
-
-
- // Assert
- Assert.That(user.HasIdentity, Is.True);
- }
- }
-
- [Test]
- public void Can_Perform_Multiple_Adds_On_UserRepository()
- {
- // Arrange
- var provider = TestObjects.GetScopeProvider(Logger);
- using (var scope = provider.CreateScope())
- {
- var repository = CreateRepository(provider);
-
- var user1 = MockedUser.CreateUser("1");
- var use2 = MockedUser.CreateUser("2");
-
- // Act
- repository.Save(user1);
-
- repository.Save(use2);
-
-
- // Assert
- Assert.That(user1.HasIdentity, Is.True);
- Assert.That(use2.HasIdentity, Is.True);
- }
- }
-
- [Test]
- public void Can_Verify_Fresh_Entity_Is_Not_Dirty()
- {
- // Arrange
- var provider = TestObjects.GetScopeProvider(Logger);
- using (var scope = provider.CreateScope())
- {
- var repository = CreateRepository(provider);
-
- var user = MockedUser.CreateUser();
- repository.Save(user);
-
-
- // Act
- var resolved = repository.Get((int)user.Id);
- bool dirty = ((User)resolved).IsDirty();
-
- // Assert
- Assert.That(dirty, Is.False);
- }
- }
-
[Test]
public void Can_Perform_Update_On_UserRepository()
{
@@ -206,268 +139,6 @@ namespace Umbraco.Tests.Persistence.Repositories
}
}
- [Test]
- public void Can_Perform_Delete_On_UserRepository()
- {
- // Arrange
- var provider = TestObjects.GetScopeProvider(Logger);
- using (var scope = provider.CreateScope())
- {
- var repository = CreateRepository(provider);
-
- var user = MockedUser.CreateUser();
-
- // Act
- repository.Save(user);
-
- var id = user.Id;
-
- var repository2 = new UserRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, Mock.Of(),TestObjects.GetGlobalSettings(), Mock.Of());
-
- repository2.Delete(user);
-
-
- var resolved = repository2.Get((int) id);
-
- // Assert
- Assert.That(resolved, Is.Null);
- }
- }
-
- [Test]
- public void Can_Perform_Get_On_UserRepository()
- {
- // Arrange
- var provider = TestObjects.GetScopeProvider(Logger);
- using (var scope = provider.CreateScope())
- {
- var repository = CreateRepository(provider);
- var userGroupRepository = CreateUserGroupRepository(provider);
-
- var user = CreateAndCommitUserWithGroup(repository, userGroupRepository);
-
- // Act
- var updatedItem = repository.Get(user.Id);
-
- // FIXME: this test cannot work, user has 2 sections but the way it's created,
- // they don't show, so the comparison with updatedItem fails - fix!
-
- // Assert
- AssertPropertyValues(updatedItem, user);
- }
- }
-
- [Test]
- public void Can_Perform_GetByQuery_On_UserRepository()
- {
- // Arrange
- var provider = TestObjects.GetScopeProvider(Logger);
- using (var scope = provider.CreateScope())
- {
- var repository = CreateRepository(provider);
-
- CreateAndCommitMultipleUsers(repository);
-
- // Act
- var query = scope.SqlContext.Query().Where(x => x.Username == "TestUser1");
- var result = repository.Get(query);
-
- // Assert
- Assert.That(result.Count(), Is.GreaterThanOrEqualTo(1));
- }
- }
-
- [Test]
- public void Can_Perform_GetAll_By_Param_Ids_On_UserRepository()
- {
- // Arrange
- var provider = TestObjects.GetScopeProvider(Logger);
- using (var scope = provider.CreateScope())
- {
- var repository = CreateRepository(provider);
-
- var users = CreateAndCommitMultipleUsers(repository);
-
- // Act
- var result = repository.GetMany((int) users[0].Id, (int) users[1].Id);
-
- // Assert
- Assert.That(result, Is.Not.Null);
- Assert.That(result.Any(), Is.True);
- Assert.That(result.Count(), Is.EqualTo(2));
- }
- }
-
- [Test]
- public void Can_Perform_GetAll_On_UserRepository()
- {
- // Arrange
- var provider = TestObjects.GetScopeProvider(Logger);
- using (var scope = provider.CreateScope())
- {
- var repository = CreateRepository(provider);
-
- CreateAndCommitMultipleUsers(repository);
-
- // Act
- var result = repository.GetMany();
-
- // Assert
- Assert.That(result, Is.Not.Null);
- Assert.That(result.Any(), Is.True);
- Assert.That(result.Count(), Is.GreaterThanOrEqualTo(3));
- }
- }
-
- [Test]
- public void Can_Perform_Exists_On_UserRepository()
- {
- // Arrange
- var provider = TestObjects.GetScopeProvider(Logger);
- using (var scope = provider.CreateScope())
- {
- var repository = CreateRepository(provider);
-
- var users = CreateAndCommitMultipleUsers(repository);
-
- // Act
- var exists = repository.Exists(users[0].Id);
-
- // Assert
- Assert.That(exists, Is.True);
- }
- }
-
- [Test]
- public void Can_Perform_Count_On_UserRepository()
- {
- // Arrange
- var provider = TestObjects.GetScopeProvider(Logger);
- using (var scope = provider.CreateScope())
- {
- var repository = CreateRepository(provider);
-
- var users = CreateAndCommitMultipleUsers(repository);
-
- // Act
- var query = scope.SqlContext.Query().Where(x => x.Username == "TestUser1" || x.Username == "TestUser2");
- var result = repository.Count(query);
-
- // Assert
- Assert.AreEqual(2, result);
- }
- }
-
- [Test]
- public void Can_Get_Paged_Results_By_Query_And_Filter_And_Groups()
- {
- var provider = TestObjects.GetScopeProvider(Logger);
- using (var scope = provider.CreateScope())
- {
- var repository = CreateRepository(provider);
-
- var users = CreateAndCommitMultipleUsers(repository);
- var query = provider.SqlContext.Query().Where(x => x.Username == "TestUser1" || x.Username == "TestUser2");
-
- try
- {
- scope.Database.AsUmbracoDatabase().EnableSqlTrace = true;
- scope.Database.AsUmbracoDatabase().EnableSqlCount = true;
-
- // Act
- var result = repository.GetPagedResultsByQuery(query, 0, 10, out var totalRecs, user => user.Id, Direction.Ascending,
- excludeUserGroups: new[] { Constants.Security.TranslatorGroupAlias },
- filter: provider.SqlContext.Query().Where(x => x.Id > -1));
-
- // Assert
- Assert.AreEqual(2, totalRecs);
- }
- finally
- {
- scope.Database.AsUmbracoDatabase().EnableSqlTrace = false;
- scope.Database.AsUmbracoDatabase().EnableSqlCount = false;
- }
- }
-
- }
-
- [Test]
- public void Can_Get_Paged_Results_With_Filter_And_Groups()
- {
- var provider = TestObjects.GetScopeProvider(Logger);
- using (var scope = provider.CreateScope())
- {
- var repository = CreateRepository(provider);
-
- var users = CreateAndCommitMultipleUsers(repository);
-
- try
- {
- scope.Database.AsUmbracoDatabase().EnableSqlTrace = true;
- scope.Database.AsUmbracoDatabase().EnableSqlCount = true;
-
- // Act
- var result = repository.GetPagedResultsByQuery(null, 0, 10, out var totalRecs, user => user.Id, Direction.Ascending,
- includeUserGroups: new[] { Constants.Security.AdminGroupAlias, Constants.Security.SensitiveDataGroupAlias },
- excludeUserGroups: new[] { Constants.Security.TranslatorGroupAlias },
- filter: provider.SqlContext.Query().Where(x => x.Id == -1));
-
- // Assert
- Assert.AreEqual(1, totalRecs);
- }
- finally
- {
- scope.Database.AsUmbracoDatabase().EnableSqlTrace = false;
- scope.Database.AsUmbracoDatabase().EnableSqlCount = false;
- }
- }
- }
-
- [Test]
- public void Can_Invalidate_SecurityStamp_On_Username_Change()
- {
- // Arrange
- var provider = TestObjects.GetScopeProvider(Logger);
- using (var scope = provider.CreateScope())
- {
- var repository = CreateRepository(provider);
- var userGroupRepository = CreateUserGroupRepository(provider);
-
- var user = CreateAndCommitUserWithGroup(repository, userGroupRepository);
- var originalSecurityStamp = user.SecurityStamp;
-
- // Ensure when user generated a security stamp is present
- Assert.That(user.SecurityStamp, Is.Not.Null);
- Assert.That(user.SecurityStamp, Is.Not.Empty);
-
- // Update username
- user.Username = user.Username + "UPDATED";
- repository.Save(user);
-
- // Get the user
- var updatedUser = repository.Get(user.Id);
-
- // Ensure the Security Stamp is invalidated & no longer the same
- Assert.AreNotEqual(originalSecurityStamp, updatedUser.SecurityStamp);
- }
- }
-
- private void AssertPropertyValues(IUser updatedItem, IUser originalUser)
- {
- Assert.That(updatedItem.Id, Is.EqualTo(originalUser.Id));
- Assert.That(updatedItem.Name, Is.EqualTo(originalUser.Name));
- Assert.That(updatedItem.Language, Is.EqualTo(originalUser.Language));
- Assert.That(updatedItem.IsApproved, Is.EqualTo(originalUser.IsApproved));
- Assert.That(updatedItem.RawPasswordValue, Is.EqualTo(originalUser.RawPasswordValue));
- Assert.That(updatedItem.IsLockedOut, Is.EqualTo(originalUser.IsLockedOut));
- Assert.IsTrue(updatedItem.StartContentIds.UnsortedSequenceEqual(originalUser.StartContentIds));
- Assert.IsTrue(updatedItem.StartMediaIds.UnsortedSequenceEqual(originalUser.StartMediaIds));
- Assert.That(updatedItem.Email, Is.EqualTo(originalUser.Email));
- Assert.That(updatedItem.Username, Is.EqualTo(originalUser.Username));
- Assert.That(updatedItem.AllowedSections.Count(), Is.EqualTo(originalUser.AllowedSections.Count()));
- foreach (var allowedSection in originalUser.AllowedSections)
- Assert.IsTrue(updatedItem.AllowedSections.Contains(allowedSection));
- }
private static User CreateAndCommitUserWithGroup(IUserRepository repository, IUserGroupRepository userGroupRepository)
{
@@ -483,15 +154,5 @@ namespace Umbraco.Tests.Persistence.Repositories
return user;
}
- private IUser[] CreateAndCommitMultipleUsers(IUserRepository repository)
- {
- var user1 = MockedUser.CreateUser("1");
- var user2 = MockedUser.CreateUser("2");
- var user3 = MockedUser.CreateUser("3");
- repository.Save(user1);
- repository.Save(user2);
- repository.Save(user3);
- return new IUser[] { user1, user2, user3 };
- }
}
}
diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs
index a07be868a5..49444f8b68 100644
--- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs
+++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs
@@ -4,24 +4,19 @@ using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
-using System.Web;
using Moq;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
-using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
-using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Services;
using Umbraco.Tests.Common;
using Umbraco.Web;
using Umbraco.Web.PublishedCache;
-using Umbraco.Web.Routing;
-using Umbraco.Web.Security;
namespace Umbraco.Tests.TestHelpers
{
diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs
index 13d5cc0328..94fac6c158 100644
--- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs
+++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs
@@ -246,17 +246,16 @@ namespace Umbraco.Tests.TestHelpers
// mappersBuilder.AddCore();
// var mappers = mappersBuilder.CreateCollection();
var mappers = Current.Factory.GetInstance();
- databaseFactory = new UmbracoDatabaseFactory(
- Constants.System.UmbracoConnectionName,
+ databaseFactory = new UmbracoDatabaseFactory(logger,
SettingsForTests.GetDefaultGlobalSettings(),
new ConnectionStrings(),
- logger,
+ Constants.System.UmbracoConnectionName,
new Lazy(() => mappers),
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();
var scopeProvider = new ScopeProvider(databaseFactory, fileSystems, coreDebug, mediaFileSystem, logger, typeFinder, NoAppCache.Instance);
diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs
index fbfada118a..b4db4f551c 100644
--- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs
+++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs
@@ -89,7 +89,7 @@ namespace Umbraco.Tests.TestHelpers
return TestObjects.GetDatabaseFactoryMock();
var lazyMappers = new Lazy(f.GetInstance);
- var factory = new UmbracoDatabaseFactory(GetDbConnectionString(), GetDbProviderName(), f.GetInstance(), lazyMappers, TestHelper.DbProviderFactoryCreator);
+ var factory = new UmbracoDatabaseFactory(f.GetInstance(), GetDbConnectionString(), GetDbProviderName(), lazyMappers, TestHelper.DbProviderFactoryCreator);
factory.ResetForTests();
return factory;
});
diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
index 0345aab2da..c3505a23fa 100644
--- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
+++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
@@ -462,13 +462,13 @@ namespace Umbraco.Tests.Testing
var globalSettings = TestHelper.GetConfigs().Global();
var connectionStrings = TestHelper.GetConfigs().ConnectionStrings();
- Composition.RegisterUnique(f => new UmbracoDatabaseFactory(
- Constants.System.UmbracoConnectionName,
+ Composition.RegisterUnique(f => new UmbracoDatabaseFactory(Logger,
globalSettings,
connectionStrings,
- Logger,
+ Constants.System.UmbracoConnectionName,
new Lazy(f.GetInstance),
TestHelper.DbProviderFactoryCreator));
+
Composition.RegisterUnique(f => f.TryGetInstance().SqlContext);
Composition.WithCollectionBuilder(); // empty
diff --git a/src/Umbraco.Tests/Testing/UmbracoTestOptions.cs b/src/Umbraco.Tests/Testing/UmbracoTestOptions.cs
deleted file mode 100644
index da3ffccc55..0000000000
--- a/src/Umbraco.Tests/Testing/UmbracoTestOptions.cs
+++ /dev/null
@@ -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
- }
- }
-}
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index 33fd731088..bb1a907843 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -150,6 +150,7 @@
+
@@ -233,11 +234,8 @@
-
-
-
@@ -269,7 +267,6 @@
-
@@ -346,7 +343,6 @@
-