Skip to content

Commit 8d0783d

Browse files
committed
Added a log level switch to the testing classes.
1 parent 220097b commit 8d0783d

File tree

16 files changed

+388
-112
lines changed

16 files changed

+388
-112
lines changed

src/Thinktecture.EntityFrameworkCore.SqlServer.Testing/EntityFrameworkCore/Testing/SqlServerTestDbContextProvider.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Microsoft.EntityFrameworkCore.Infrastructure;
66
using Microsoft.EntityFrameworkCore.Migrations;
77
using Microsoft.EntityFrameworkCore.Storage;
8+
using Thinktecture.Logging;
89

910
namespace Thinktecture.EntityFrameworkCore.Testing;
1011

@@ -25,6 +26,7 @@ public class SqlServerTestDbContextProvider<T> : ITestDbContextProvider<T>
2526
private readonly DbConnection _masterConnection;
2627
private readonly IReadOnlyList<Action<T>> _contextInitializations;
2728
private readonly Func<DbContextOptions<T>, IDbDefaultSchema, T>? _contextFactory;
29+
private readonly TestingLoggingOptions _testingLoggingOptions;
2830

2931
private T? _arrangeDbContext;
3032
private T? _actDbContext;
@@ -50,7 +52,12 @@ public class SqlServerTestDbContextProvider<T> : ITestDbContextProvider<T>
5052
/// <summary>
5153
/// Contains executed commands if this feature was activated.
5254
/// </summary>
53-
public IReadOnlyCollection<string>? ExecutedCommands { get; }
55+
public IReadOnlyCollection<string>? ExecutedCommands => _testingLoggingOptions.ExecutedCommands;
56+
57+
/// <summary>
58+
/// Log level switch.
59+
/// </summary>
60+
public TestingLogLevelSwitch LogLevelSwitch => _testingLoggingOptions.LogLevelSwitch;
5461

5562
/// <summary>
5663
/// Initializes a new instance of <see cref="SqlServerTestDbContextProvider{T}"/>
@@ -66,7 +73,7 @@ protected internal SqlServerTestDbContextProvider(SqlServerTestDbContextProvider
6673
_masterDbContextOptions = options.MasterDbContextOptions ?? throw new ArgumentException($"The '{nameof(options.MasterDbContextOptions)}' cannot be null.", nameof(options));
6774
_dbContextOptions = options.DbContextOptions ?? throw new ArgumentException($"The '{nameof(options.DbContextOptions)}' cannot be null.", nameof(options));
6875
_migrationExecutionStrategy = options.MigrationExecutionStrategy ?? throw new ArgumentException($"The '{nameof(options.MigrationExecutionStrategy)}' cannot be null.", nameof(options));
69-
ExecutedCommands = options.ExecutedCommands;
76+
_testingLoggingOptions = options.TestingLoggingOptions ?? throw new ArgumentException($"The '{nameof(options.TestingLoggingOptions)}' cannot be null.", nameof(options));
7077
_contextInitializations = options.ContextInitializations ?? throw new ArgumentException($"The '{nameof(options.ContextInitializations)}' cannot be null.", nameof(options));
7178
_contextFactory = options.ContextFactory;
7279
}
@@ -173,7 +180,18 @@ protected virtual void RunMigrations(T ctx)
173180
// concurrent execution is not supported by EF migrations
174181
lock (_locks.GetOrAdd(Schema, _ => new object()))
175182
{
176-
_migrationExecutionStrategy.Migrate(ctx);
183+
var logLevel = LogLevelSwitch.MinimumLogLevel;
184+
185+
try
186+
{
187+
LogLevelSwitch.MinimumLogLevel = _testingLoggingOptions.MigrationLogLevel;
188+
189+
_migrationExecutionStrategy.Migrate(ctx);
190+
}
191+
finally
192+
{
193+
LogLevelSwitch.MinimumLogLevel = logLevel;
194+
}
177195
}
178196
}
179197

src/Thinktecture.EntityFrameworkCore.SqlServer.Testing/EntityFrameworkCore/Testing/SqlServerTestDbContextProviderBuilder.cs

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Microsoft.Extensions.Logging;
66
using Thinktecture.EntityFrameworkCore.Infrastructure;
77
using Thinktecture.EntityFrameworkCore.Migrations;
8+
using Thinktecture.Logging;
89
using Xunit.Abstractions;
910

1011
namespace Thinktecture.EntityFrameworkCore.Testing;
@@ -13,7 +14,7 @@ namespace Thinktecture.EntityFrameworkCore.Testing;
1314
/// Builder for the <see cref="SqlServerTestDbContextProvider{T}"/>.
1415
/// </summary>
1516
/// <typeparam name="T">Type of the <see cref="DbContext"/>.</typeparam>
16-
public class SqlServerTestDbContextProviderBuilder<T>
17+
public class SqlServerTestDbContextProviderBuilder<T> : TestDbContextProviderBuilder
1718
where T : DbContext
1819
{
1920
private const string _HISTORY_TABLE_NAME = "__EFMigrationsHistory";
@@ -25,11 +26,8 @@ public class SqlServerTestDbContextProviderBuilder<T>
2526
private readonly List<Action<T>> _ctxInitializations;
2627

2728
private IMigrationExecutionStrategy? _migrationExecutionStrategy;
28-
private ILoggerFactory? _loggerFactory;
29-
private bool _enableSensitiveDataLogging;
3029
private bool _disableModelCache;
3130
private bool _useThinktectureSqlServerMigrationsSqlGenerator = true;
32-
private bool _collectExecutedCommands;
3331
private string? _sharedTablesSchema;
3432
private Func<DbContextOptions<T>, IDbDefaultSchema, T>? _contextFactory;
3533

@@ -67,10 +65,12 @@ public SqlServerTestDbContextProviderBuilder<T> UseMigrationExecutionStrategy(IM
6765
/// </summary>
6866
/// <param name="loggerFactory">Logger factory to use.</param>
6967
/// <param name="enableSensitiveDataLogging">Enables or disables sensitive data logging.</param>
70-
public SqlServerTestDbContextProviderBuilder<T> UseLogging(ILoggerFactory? loggerFactory, bool enableSensitiveDataLogging = true)
68+
/// <returns>Current builder for chaining.</returns>
69+
public new SqlServerTestDbContextProviderBuilder<T> UseLogging(
70+
ILoggerFactory? loggerFactory,
71+
bool enableSensitiveDataLogging = true)
7172
{
72-
_loggerFactory = loggerFactory;
73-
_enableSensitiveDataLogging = enableSensitiveDataLogging;
73+
base.UseLogging(loggerFactory, enableSensitiveDataLogging);
7474

7575
return this;
7676
}
@@ -81,14 +81,27 @@ public SqlServerTestDbContextProviderBuilder<T> UseLogging(ILoggerFactory? logge
8181
/// <param name="testOutputHelper">XUnit output.</param>
8282
/// <param name="enableSensitiveDataLogging">Enables or disables sensitive data logging.</param>
8383
/// <param name="outputTemplate">The serilog output template.</param>
84-
public SqlServerTestDbContextProviderBuilder<T> UseLogging(
84+
/// <returns>Current builder for chaining.</returns>
85+
public new SqlServerTestDbContextProviderBuilder<T> UseLogging(
8586
ITestOutputHelper? testOutputHelper,
8687
bool enableSensitiveDataLogging = true,
8788
string? outputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] [{SourceContext}] {Message:lj}{NewLine}{Exception}")
8889
{
89-
var loggerFactory = testOutputHelper?.ToLoggerFactory(outputTemplate);
90+
base.UseLogging(testOutputHelper, enableSensitiveDataLogging, outputTemplate);
9091

91-
return UseLogging(loggerFactory, enableSensitiveDataLogging);
92+
return this;
93+
}
94+
95+
/// <summary>
96+
/// Sets the log level during migrations.
97+
/// </summary>
98+
/// <param name="logLevel">Minimum log level to use during migrations.</param>
99+
/// <returns>Current builder for chaining.</returns>
100+
public new SqlServerTestDbContextProviderBuilder<T> UseMigrationLogLevel(LogLevel logLevel)
101+
{
102+
base.UseMigrationLogLevel(logLevel);
103+
104+
return this;
92105
}
93106

94107
/// <summary>
@@ -146,9 +159,9 @@ public SqlServerTestDbContextProviderBuilder<T> UseThinktectureSqlServerMigratio
146159
/// Indication whether collect executed commands or not.
147160
/// </summary>
148161
/// <returns>Current builder for chaining</returns>
149-
public SqlServerTestDbContextProviderBuilder<T> CollectExecutedCommands(bool collectExecutedCommands = true)
162+
public new SqlServerTestDbContextProviderBuilder<T> CollectExecutedCommands(bool collectExecutedCommands = true)
150163
{
151-
_collectExecutedCommands = collectExecutedCommands;
164+
base.CollectExecutedCommands(collectExecutedCommands);
152165

153166
return this;
154167
}
@@ -161,6 +174,9 @@ public SqlServerTestDbContextProviderBuilder<T> CollectExecutedCommands(bool col
161174
/// <returns>Current builder for chaining.</returns>
162175
public SqlServerTestDbContextProviderBuilder<T> UseSharedTableSchema(string schema)
163176
{
177+
if (String.IsNullOrWhiteSpace(schema))
178+
throw new ArgumentException("Schema cannot be empty.", nameof(schema));
179+
164180
_sharedTablesSchema = schema;
165181

166182
return this;
@@ -185,7 +201,7 @@ public SqlServerTestDbContextProviderBuilder<T> InitializeContext(Action<T> init
185201
/// </summary>
186202
/// <param name="contextFactory">Factory to create the context of type <typeparamref name="T"/>.</param>
187203
/// <returns>Current builder for chaining.</returns>
188-
public SqlServerTestDbContextProviderBuilder<T> UseContextFactory(Func<DbContextOptions<T>, IDbDefaultSchema, T> contextFactory)
204+
public SqlServerTestDbContextProviderBuilder<T> UseContextFactory(Func<DbContextOptions<T>, IDbDefaultSchema, T>? contextFactory)
189205
{
190206
_contextFactory = contextFactory;
191207

@@ -214,22 +230,22 @@ public virtual DbContextOptionsBuilder<T> CreateOptionsBuilder(
214230
DbConnection? connection,
215231
string schema)
216232
{
217-
var loggerFactory = GetLoggerFactory(out _);
233+
var loggingOptions = CreateLoggingOptions();
218234

219-
return CreateOptionsBuilder(connection, schema, loggerFactory);
235+
return CreateOptionsBuilder(connection, schema, loggingOptions);
220236
}
221237

222238
/// <summary>
223239
/// Creates and configures the <see cref="DbContextOptionsBuilder{TContext}"/>
224240
/// </summary>
225241
/// <param name="connection">Database connection to use.</param>
226242
/// <param name="schema">Database schema to use.</param>
227-
/// <param name="loggerFactory">Logger factory to use.</param>
243+
/// <param name="loggingOptions">Logging options.</param>
228244
/// <returns>An instance of <see cref="DbContextOptionsBuilder{TContext}"/></returns>
229245
protected virtual DbContextOptionsBuilder<T> CreateOptionsBuilder(
230246
DbConnection? connection,
231247
string schema,
232-
ILoggerFactory? loggerFactory)
248+
TestingLoggingOptions loggingOptions)
233249
{
234250
var builder = new DbContextOptionsBuilder<T>();
235251

@@ -242,16 +258,13 @@ protected virtual DbContextOptionsBuilder<T> CreateOptionsBuilder(
242258
builder.UseSqlServer(connection, optionsBuilder => ConfigureSqlServer(optionsBuilder, schema));
243259
}
244260

245-
builder.AddSchemaRespectingComponents();
261+
builder.AddSchemaRespectingComponents()
262+
.UseLoggerFactory(loggingOptions.LoggerFactory)
263+
.EnableSensitiveDataLogging(loggingOptions.EnableSensitiveDataLogging);
246264

247265
if (_disableModelCache)
248266
builder.ReplaceService<IModelCacheKeyFactory, CachePerContextModelCacheKeyFactory>();
249267

250-
builder.EnableSensitiveDataLogging(_enableSensitiveDataLogging);
251-
252-
if (loggerFactory != null)
253-
builder.UseLoggerFactory(loggerFactory);
254-
255268
_configuresOptionsCollection.ForEach(configure => configure(builder, schema));
256269

257270
return builder;
@@ -288,19 +301,19 @@ public SqlServerTestDbContextProvider<T> Build()
288301

289302
try
290303
{
291-
var loggerFactory = GetLoggerFactory(out var executedCommands);
292-
var masterDbContextOptions = CreateOptionsBuilder(masterConnection, schema, loggerFactory).Options;
293-
var dbContextOptions = CreateOptionsBuilder(null, schema, loggerFactory).Options;
304+
var loggingOptions = CreateLoggingOptions();
305+
var masterDbContextOptions = CreateOptionsBuilder(masterConnection, schema, loggingOptions).Options;
306+
var dbContextOptions = CreateOptionsBuilder(null, schema, loggingOptions).Options;
294307

295308
return new SqlServerTestDbContextProvider<T>(new SqlServerTestDbContextProviderOptions<T>(masterConnection,
296309
_migrationExecutionStrategy ?? IMigrationExecutionStrategy.Migrations,
297310
masterDbContextOptions,
298311
dbContextOptions,
312+
loggingOptions,
299313
_ctxInitializations.ToList(),
300314
schema)
301315
{
302316
IsUsingSharedTables = _useSharedTables,
303-
ExecutedCommands = executedCommands,
304317
ContextFactory = _contextFactory
305318
});
306319
}
@@ -310,21 +323,4 @@ public SqlServerTestDbContextProvider<T> Build()
310323
throw;
311324
}
312325
}
313-
314-
private ILoggerFactory? GetLoggerFactory(out IReadOnlyCollection<string>? executedCommands)
315-
{
316-
var loggerFactory = _loggerFactory;
317-
318-
if (_collectExecutedCommands)
319-
{
320-
loggerFactory ??= new LoggerFactory();
321-
executedCommands = loggerFactory.CollectExecutedCommands();
322-
}
323-
else
324-
{
325-
executedCommands = null;
326-
}
327-
328-
return loggerFactory;
329-
}
330326
}

src/Thinktecture.EntityFrameworkCore.SqlServer.Testing/EntityFrameworkCore/Testing/SqlServerTestDbContextProviderOptions.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Data.Common;
2+
using Thinktecture.Logging;
23

34
namespace Thinktecture.EntityFrameworkCore.Testing;
45

@@ -33,9 +34,10 @@ public SqlServerTestDbContextProviderOptions(
3334
IMigrationExecutionStrategy migrationExecutionStrategy,
3435
DbContextOptions<T> masterDbContextOptions,
3536
DbContextOptions<T> dbContextOptions,
37+
TestingLoggingOptions testingLoggingOptions,
3638
IReadOnlyList<Action<T>> contextInitializations,
3739
string schema)
38-
: base(masterConnection, migrationExecutionStrategy, masterDbContextOptions, dbContextOptions, contextInitializations)
40+
: base(masterConnection, migrationExecutionStrategy, masterDbContextOptions, dbContextOptions, testingLoggingOptions, contextInitializations)
3941
{
4042
Schema = schema;
4143
}

src/Thinktecture.EntityFrameworkCore.Sqlite.Testing/EntityFrameworkCore/Testing/SqlServerTestDbContextProviderOptions.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Data.Common;
2+
using Thinktecture.Logging;
23

34
namespace Thinktecture.EntityFrameworkCore.Testing;
45

@@ -27,9 +28,10 @@ public SqliteTestDbContextProviderOptions(
2728
IMigrationExecutionStrategy migrationExecutionStrategy,
2829
DbContextOptions<T> masterDbContextOptions,
2930
DbContextOptions<T> dbContextOptions,
31+
TestingLoggingOptions testingLoggingOptions,
3032
IReadOnlyList<Action<T>> contextInitializations,
3133
string connectionString)
32-
: base(masterConnection, migrationExecutionStrategy, masterDbContextOptions, dbContextOptions, contextInitializations)
34+
: base(masterConnection, migrationExecutionStrategy, masterDbContextOptions, dbContextOptions, testingLoggingOptions, contextInitializations)
3335
{
3436
ConnectionString = connectionString;
3537
}

src/Thinktecture.EntityFrameworkCore.Sqlite.Testing/EntityFrameworkCore/Testing/SqliteTestDbContextProvider.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Data.Common;
22
using Microsoft.EntityFrameworkCore.Infrastructure;
3+
using Thinktecture.Logging;
34

45
namespace Thinktecture.EntityFrameworkCore.Testing;
56

@@ -24,6 +25,7 @@ public class SqliteTestDbContextProvider<T> : ITestDbContextProvider<T>
2425
private T? _actDbContext;
2526
private T? _assertDbContext;
2627
private bool _isAtLeastOneContextCreated;
28+
private readonly TestingLoggingOptions _testingLoggingOptions;
2729

2830
/// <inheritdoc />
2931
public T ArrangeDbContext => _arrangeDbContext ??= CreateDbContext(true);
@@ -37,7 +39,12 @@ public class SqliteTestDbContextProvider<T> : ITestDbContextProvider<T>
3739
/// <summary>
3840
/// Contains executed commands if this feature was activated.
3941
/// </summary>
40-
public IReadOnlyCollection<string>? ExecutedCommands { get; }
42+
public IReadOnlyCollection<string>? ExecutedCommands => _testingLoggingOptions.ExecutedCommands;
43+
44+
/// <summary>
45+
/// Log level switch.
46+
/// </summary>
47+
public TestingLogLevelSwitch LogLevelSwitch => _testingLoggingOptions.LogLevelSwitch;
4148

4249
/// <summary>
4350
/// The connection string.
@@ -57,7 +64,7 @@ protected internal SqliteTestDbContextProvider(SqliteTestDbContextProviderOption
5764
_masterDbContextOptions = options.MasterDbContextOptions ?? throw new ArgumentException($"The '{nameof(options.MasterDbContextOptions)}' cannot be null.", nameof(options));
5865
_dbContextOptions = options.DbContextOptions ?? throw new ArgumentException($"The '{nameof(options.DbContextOptions)}' cannot be null.", nameof(options));
5966
_migrationExecutionStrategy = options.MigrationExecutionStrategy ?? throw new ArgumentException($"The '{nameof(options.MigrationExecutionStrategy)}' cannot be null.", nameof(options));
60-
ExecutedCommands = options.ExecutedCommands;
67+
_testingLoggingOptions = options.TestingLoggingOptions ?? throw new ArgumentException($"The '{nameof(options.TestingLoggingOptions)}' cannot be null.", nameof(options));
6168
_contextInitializations = options.ContextInitializations ?? throw new ArgumentException($"The '{nameof(options.ContextInitializations)}' cannot be null.", nameof(options));
6269
_contextFactory = options.ContextFactory;
6370
}
@@ -125,7 +132,17 @@ protected virtual void RunMigrations(T ctx)
125132
// concurrent execution is not supported by EF migrations
126133
lock (_lock)
127134
{
128-
_migrationExecutionStrategy.Migrate(ctx);
135+
var logLevel = LogLevelSwitch.MinimumLogLevel;
136+
try
137+
{
138+
LogLevelSwitch.MinimumLogLevel = _testingLoggingOptions.MigrationLogLevel;
139+
140+
_migrationExecutionStrategy.Migrate(ctx);
141+
}
142+
finally
143+
{
144+
LogLevelSwitch.MinimumLogLevel = logLevel;
145+
}
129146
}
130147
}
131148

0 commit comments

Comments
 (0)