Skip to content

Commit 032ab1c

Browse files
committed
Added a factory to create MSSqlSink in config extensions for better testability.
1 parent f741691 commit 032ab1c

File tree

4 files changed

+133
-22
lines changed

4 files changed

+133
-22
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using Serilog.Formatting;
3+
4+
namespace Serilog.Sinks.MSSqlServer.Configuration.Extensions.Hybrid
5+
{
6+
internal interface IMSSqlServerSinkFactory
7+
{
8+
MSSqlServerSink Create(
9+
string connectionString,
10+
string tableName,
11+
int batchPostingLimit,
12+
TimeSpan defaultedPeriod,
13+
IFormatProvider formatProvider,
14+
bool autoCreateSqlTable,
15+
ColumnOptions columnOptions,
16+
string schemaName,
17+
ITextFormatter logEventFormatter);
18+
}
19+
}

src/Serilog.Sinks.MSSqlServer/Configuration/Extensions/Hybrid/LoggerConfigurationMSSqlServerExtensions.cs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using Serilog.Events;
2121
using Serilog.Formatting;
2222
using Serilog.Sinks.MSSqlServer;
23+
using Serilog.Sinks.MSSqlServer.Configuration.Extensions.Hybrid;
2324

2425
// The "Hybrid" configuration system supports both Microsoft.Extensions.Configuration and System.Configuration.
2526
// This is necessary because .NET Framework 4.6.1+ and .NET Core 2.0+ apps support both approaches, whereas the
@@ -86,7 +87,8 @@ public static LoggerConfiguration MSSqlServer(
8687
schemaName: schemaName,
8788
logEventFormatter: logEventFormatter,
8889
applySystemConfiguration: new ApplySystemConfiguration(),
89-
applyMicrosoftExtensionsConfiguration: new ApplyMicrosoftExtensionsConfiguration());
90+
applyMicrosoftExtensionsConfiguration: new ApplyMicrosoftExtensionsConfiguration(),
91+
sinkFactory: new MSSqlServerSinkFactory());
9092

9193
// Internal overload with parameters applySystemConfiguration and applyMicrosoftExtensionsConfiguration used by tests to inject mocks
9294
internal static LoggerConfiguration MSSqlServerInternal(
@@ -104,7 +106,8 @@ internal static LoggerConfiguration MSSqlServerInternal(
104106
string schemaName = "dbo",
105107
ITextFormatter logEventFormatter = null,
106108
IApplySystemConfiguration applySystemConfiguration = null,
107-
IApplyMicrosoftExtensionsConfiguration applyMicrosoftExtensionsConfiguration = null)
109+
IApplyMicrosoftExtensionsConfiguration applyMicrosoftExtensionsConfiguration = null,
110+
IMSSqlServerSinkFactory sinkFactory = null)
108111
{
109112
if (loggerConfiguration == null)
110113
throw new ArgumentNullException(nameof(loggerConfiguration));
@@ -122,24 +125,20 @@ internal static LoggerConfiguration MSSqlServerInternal(
122125
SelfLog.WriteLine("Warning: Both System.Configuration (app.config or web.config) and Microsoft.Extensions.Configuration are being applied to the MSSQLServer sink.");
123126
}
124127

125-
if (appConfiguration != null || columnOptionsSection != null)
128+
if (appConfiguration != null)
126129
{
127130
connStr = applyMicrosoftExtensionsConfiguration.GetConnectionString(connStr, appConfiguration);
131+
}
132+
133+
if (columnOptionsSection != null)
134+
{
128135
colOpts = applyMicrosoftExtensionsConfiguration.ConfigureColumnOptions(colOpts, columnOptionsSection);
129136
}
130137

131-
return loggerConfiguration.Sink(
132-
new MSSqlServerSink(
133-
connStr,
134-
tableName,
135-
batchPostingLimit,
136-
defaultedPeriod,
137-
formatProvider,
138-
autoCreateSqlTable,
139-
colOpts,
140-
schemaName,
141-
logEventFormatter),
142-
restrictedToMinimumLevel);
138+
var sink = sinkFactory.Create(connStr, tableName, batchPostingLimit, defaultedPeriod, formatProvider,
139+
autoCreateSqlTable, colOpts, schemaName, logEventFormatter);
140+
141+
return loggerConfiguration.Sink(sink, restrictedToMinimumLevel);
143142
}
144143

145144
/// <summary>
@@ -215,9 +214,13 @@ internal static LoggerConfiguration MSSqlServerInternal(
215214
SelfLog.WriteLine("Warning: Both System.Configuration (app.config or web.config) and Microsoft.Extensions.Configuration are being applied to the MSSQLServer sink.");
216215
}
217216

218-
if (appConfiguration != null || columnOptionsSection != null)
217+
if (appConfiguration != null)
219218
{
220219
connStr = applyMicrosoftExtensionsConfiguration.GetConnectionString(connStr, appConfiguration);
220+
}
221+
222+
if (columnOptionsSection != null)
223+
{
221224
colOpts = applyMicrosoftExtensionsConfiguration.ConfigureColumnOptions(colOpts, columnOptionsSection);
222225
}
223226

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using Serilog.Formatting;
3+
4+
namespace Serilog.Sinks.MSSqlServer.Configuration.Extensions.Hybrid
5+
{
6+
internal class MSSqlServerSinkFactory : IMSSqlServerSinkFactory
7+
{
8+
public MSSqlServerSink Create(
9+
string connectionString,
10+
string tableName,
11+
int batchPostingLimit,
12+
TimeSpan defaultedPeriod,
13+
IFormatProvider formatProvider,
14+
bool autoCreateSqlTable,
15+
ColumnOptions columnOptions,
16+
string schemaName,
17+
ITextFormatter logEventFormatter)
18+
{
19+
return new MSSqlServerSink(
20+
connectionString,
21+
tableName,
22+
batchPostingLimit,
23+
defaultedPeriod,
24+
formatProvider,
25+
autoCreateSqlTable,
26+
columnOptions,
27+
schemaName,
28+
logEventFormatter);
29+
}
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
using Microsoft.Extensions.Configuration;
1+
using System;
2+
using Microsoft.Extensions.Configuration;
23
using Moq;
4+
using Serilog.Formatting;
5+
using Serilog.Sinks.MSSqlServer.Configuration.Extensions.Hybrid;
36
using Xunit;
47

58
namespace Serilog.Sinks.MSSqlServer.Tests.Configuration.Extensions.Hybrid
@@ -10,24 +13,79 @@ public class LoggerConfigurationMSSqlServerExtensionsTests
1013
public void MSSqlServerCallsApplyMicrosoftExtensionsConfigurationGetConnectionString()
1114
{
1215
// Arrange
13-
const string connectionString = "TestConnectionString";
16+
const string inputConnectionString = "TestConnectionString";
17+
var loggerConfiguration = new LoggerConfiguration();
18+
var applyMicrosoftExtensionsConfigurationMock = new Mock<IApplyMicrosoftExtensionsConfiguration>();
19+
applyMicrosoftExtensionsConfigurationMock.Setup(c => c.GetConnectionString(It.IsAny<string>(), It.IsAny<IConfiguration>()));
20+
var appConfigurationMock = new Mock<IConfiguration>();
21+
var columnOptionsSectionMock = new Mock<IConfigurationSection>();
22+
var sinkFactoryMock = new Mock<IMSSqlServerSinkFactory>();
23+
24+
// Act
25+
loggerConfiguration.WriteTo.MSSqlServerInternal(
26+
connectionString: inputConnectionString,
27+
tableName: "TestTableName",
28+
appConfiguration: appConfigurationMock.Object,
29+
columnOptionsSection: columnOptionsSectionMock.Object,
30+
applyMicrosoftExtensionsConfiguration: applyMicrosoftExtensionsConfigurationMock.Object,
31+
sinkFactory: sinkFactoryMock.Object);
32+
33+
// Assert
34+
applyMicrosoftExtensionsConfigurationMock.Verify(c => c.GetConnectionString(inputConnectionString, appConfigurationMock.Object),
35+
Times.Once);
36+
}
37+
38+
[Fact]
39+
public void MSSqlServerCallsSinkFactoryWithConnectionStringFromConfig()
40+
{
41+
// Arrange
42+
const string inputConnectionString = "TestConnectionString";
43+
const string configConnectionString = "TestConnectionStringFromConfig";
1444
var loggerConfiguration = new LoggerConfiguration();
1545
var applyMicrosoftExtensionsConfigurationMock = new Mock<IApplyMicrosoftExtensionsConfiguration>();
1646
applyMicrosoftExtensionsConfigurationMock.Setup(c => c.GetConnectionString(It.IsAny<string>(), It.IsAny<IConfiguration>()))
17-
.Returns(connectionString);
47+
.Returns(configConnectionString);
1848
var appConfigurationMock = new Mock<IConfiguration>();
1949
var columnOptionsSectionMock = new Mock<IConfigurationSection>();
50+
var sinkFactoryMock = new Mock<IMSSqlServerSinkFactory>();
2051

2152
// Act
2253
loggerConfiguration.WriteTo.MSSqlServerInternal(
23-
connectionString: connectionString,
54+
connectionString: inputConnectionString,
2455
tableName: "TestTableName",
2556
appConfiguration: appConfigurationMock.Object,
2657
columnOptionsSection: columnOptionsSectionMock.Object,
27-
applyMicrosoftExtensionsConfiguration: applyMicrosoftExtensionsConfigurationMock.Object);
58+
applyMicrosoftExtensionsConfiguration: applyMicrosoftExtensionsConfigurationMock.Object,
59+
sinkFactory: sinkFactoryMock.Object);
60+
61+
// Assert
62+
applyMicrosoftExtensionsConfigurationMock.Verify(c => c.GetConnectionString(inputConnectionString, appConfigurationMock.Object),
63+
Times.Once);
64+
sinkFactoryMock.Verify(f => f.Create(configConnectionString, It.IsAny<string>(), It.IsAny<int>(), It.IsAny<TimeSpan>(),
65+
It.IsAny<IFormatProvider>(), It.IsAny<bool>(), It.IsAny<ColumnOptions>(), It.IsAny<string>(), It.IsAny<ITextFormatter>()), Times.Once);
66+
}
67+
68+
[Fact]
69+
public void MSSqlServerDoesNotCallApplyMicrosoftExtensionsConfigurationGetConnectionStringWhenAppConfigIsNull()
70+
{
71+
// Arrange
72+
var loggerConfiguration = new LoggerConfiguration();
73+
var applyMicrosoftExtensionsConfigurationMock = new Mock<IApplyMicrosoftExtensionsConfiguration>();
74+
var columnOptionsSectionMock = new Mock<IConfigurationSection>();
75+
var sinkFactoryMock = new Mock<IMSSqlServerSinkFactory>();
76+
77+
// Act
78+
loggerConfiguration.WriteTo.MSSqlServerInternal(
79+
connectionString: "TestConnectionString",
80+
tableName: "TestTableName",
81+
appConfiguration: null,
82+
columnOptionsSection: columnOptionsSectionMock.Object,
83+
applyMicrosoftExtensionsConfiguration: applyMicrosoftExtensionsConfigurationMock.Object,
84+
sinkFactory: sinkFactoryMock.Object);
2885

2986
// Assert
30-
applyMicrosoftExtensionsConfigurationMock.Verify(c => c.GetConnectionString(connectionString, appConfigurationMock.Object));
87+
applyMicrosoftExtensionsConfigurationMock.Verify(c => c.GetConnectionString(It.IsAny<string>(), It.IsAny<IConfiguration>()),
88+
Times.Never);
3189
}
3290
}
3391
}

0 commit comments

Comments
 (0)