Skip to content

Commit 7d624ce

Browse files
Merge branch 'master' of github.com:serilog-contrib/SerilogSinksInMemory
2 parents 199e05f + 9446b95 commit 7d624ce

25 files changed

+682
-5
lines changed

.github/workflows/dotnet.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ jobs:
7171
dotnet restore -p:Version=${{ steps.shortversion.outputs.shortversion }}
7272
dotnet test --no-restore -c Release Serilog.Sinks.InMemory.Assertions.Tests.Integration.AwesomeAssertions8.csproj
7373
74+
- name: Run integration tests for AwesomeAssertions 9
75+
working-directory: test/Serilog.Sinks.InMemory.Assertions.Tests.Integration.AwesomeAssertions9
76+
run: |
77+
dotnet restore -p:Version=${{ steps.shortversion.outputs.shortversion }}
78+
dotnet test --no-restore -c Release Serilog.Sinks.InMemory.Assertions.Tests.Integration.AwesomeAssertions9.csproj
79+
7480
- name: Run integration tests for Shouldly 4.x
7581
working-directory: test/Serilog.Sinks.InMemory.Assertions.Tests.Integration.Shouldly4
7682
run: |

.github/workflows/pre_release.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ jobs:
7676
dotnet restore -p:Version=${{ steps.shortversion.outputs.shortversion }}
7777
dotnet test --no-restore -c Release Serilog.Sinks.InMemory.Assertions.Tests.Integration.AwesomeAssertions8.csproj
7878
79+
- name: Run integration tests for AwesomeAssertions 9
80+
working-directory: test/Serilog.Sinks.InMemory.Assertions.Tests.Integration.AwesomeAssertions9
81+
run: |
82+
dotnet restore -p:Version=${{ steps.shortversion.outputs.shortversion }}
83+
dotnet test --no-restore -c Release Serilog.Sinks.InMemory.Assertions.Tests.Integration.AwesomeAssertions9.csproj
84+
7985
- name: Run integration tests for Shouldly 4.x
8086
working-directory: test/Serilog.Sinks.InMemory.Assertions.Tests.Integration.Shouldly4
8187
run: |

.github/workflows/release.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ jobs:
7979
dotnet restore -p:Version=${{ steps.shortversion.outputs.shortversion }}
8080
dotnet test --no-restore -c Release Serilog.Sinks.InMemory.Assertions.Tests.Integration.AwesomeAssertions8.csproj
8181
82+
- name: Run integration tests for AwesomeAssertions 9
83+
working-directory: test/Serilog.Sinks.InMemory.Assertions.Tests.Integration.AwesomeAssertions9
84+
run: |
85+
dotnet restore -p:Version=${{ steps.shortversion.outputs.shortversion }}
86+
dotnet test --no-restore -c Release Serilog.Sinks.InMemory.Assertions.Tests.Integration.AwesomeAssertions9.csproj
87+
8288
- name: Run integration tests for Shouldly 4.x
8389
working-directory: test/Serilog.Sinks.InMemory.Assertions.Tests.Integration.Shouldly4
8490
run: |

SerilogSinksInMemory.sln

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
2424
ProjectSection(SolutionItems) = preProject
2525
Changelog.md = Changelog.md
2626
Directory.Build.props = Directory.Build.props
27-
README.md = README.md
2827
LICENSE = LICENSE
28+
README.md = README.md
2929
EndProjectSection
3030
EndProject
3131
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serilog.Sinks.InMemory.Assertions.Tests.Unit.FluentAssertions6", "test\Serilog.Sinks.InMemory.Assertions.Tests.Unit.FluentAssertions6\Serilog.Sinks.InMemory.Assertions.Tests.Unit.FluentAssertions6.csproj", "{F65ECEEE-4461-48EE-98BE-003BBC716FC5}"
@@ -64,6 +64,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serilog.Sinks.InMemory.Asse
6464
EndProject
6565
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serilog.Sinks.InMemory.Shouldly4", "src\Serilog.Sinks.InMemory.Shouldly4\Serilog.Sinks.InMemory.Shouldly4.csproj", "{AD9FB993-5657-464E-A3B4-D8163F1AF7C4}"
6666
EndProject
67+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serilog.Sinks.InMemory.AwesomeAssertions9", "src\Serilog.Sinks.InMemory.AwesomeAssertions9\Serilog.Sinks.InMemory.AwesomeAssertions9.csproj", "{545E23F2-220C-3065-196C-3956BD778A1C}"
68+
EndProject
69+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serilog.Sinks.InMemory.Assertions.Tests.Unit.AwesomeAssertions9", "test\Serilog.Sinks.InMemory.Assertions.Tests.Unit.AwesomeAssertions9\Serilog.Sinks.InMemory.Assertions.Tests.Unit.AwesomeAssertions9.csproj", "{2F1384C1-9596-FFB7-63CC-02D250E62355}"
70+
EndProject
6771
Global
6872
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6973
Debug|Any CPU = Debug|Any CPU
@@ -266,6 +270,30 @@ Global
266270
{AD9FB993-5657-464E-A3B4-D8163F1AF7C4}.Release|x64.Build.0 = Release|Any CPU
267271
{AD9FB993-5657-464E-A3B4-D8163F1AF7C4}.Release|x86.ActiveCfg = Release|Any CPU
268272
{AD9FB993-5657-464E-A3B4-D8163F1AF7C4}.Release|x86.Build.0 = Release|Any CPU
273+
{545E23F2-220C-3065-196C-3956BD778A1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
274+
{545E23F2-220C-3065-196C-3956BD778A1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
275+
{545E23F2-220C-3065-196C-3956BD778A1C}.Debug|x64.ActiveCfg = Debug|Any CPU
276+
{545E23F2-220C-3065-196C-3956BD778A1C}.Debug|x64.Build.0 = Debug|Any CPU
277+
{545E23F2-220C-3065-196C-3956BD778A1C}.Debug|x86.ActiveCfg = Debug|Any CPU
278+
{545E23F2-220C-3065-196C-3956BD778A1C}.Debug|x86.Build.0 = Debug|Any CPU
279+
{545E23F2-220C-3065-196C-3956BD778A1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
280+
{545E23F2-220C-3065-196C-3956BD778A1C}.Release|Any CPU.Build.0 = Release|Any CPU
281+
{545E23F2-220C-3065-196C-3956BD778A1C}.Release|x64.ActiveCfg = Release|Any CPU
282+
{545E23F2-220C-3065-196C-3956BD778A1C}.Release|x64.Build.0 = Release|Any CPU
283+
{545E23F2-220C-3065-196C-3956BD778A1C}.Release|x86.ActiveCfg = Release|Any CPU
284+
{545E23F2-220C-3065-196C-3956BD778A1C}.Release|x86.Build.0 = Release|Any CPU
285+
{2F1384C1-9596-FFB7-63CC-02D250E62355}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
286+
{2F1384C1-9596-FFB7-63CC-02D250E62355}.Debug|Any CPU.Build.0 = Debug|Any CPU
287+
{2F1384C1-9596-FFB7-63CC-02D250E62355}.Debug|x64.ActiveCfg = Debug|Any CPU
288+
{2F1384C1-9596-FFB7-63CC-02D250E62355}.Debug|x64.Build.0 = Debug|Any CPU
289+
{2F1384C1-9596-FFB7-63CC-02D250E62355}.Debug|x86.ActiveCfg = Debug|Any CPU
290+
{2F1384C1-9596-FFB7-63CC-02D250E62355}.Debug|x86.Build.0 = Debug|Any CPU
291+
{2F1384C1-9596-FFB7-63CC-02D250E62355}.Release|Any CPU.ActiveCfg = Release|Any CPU
292+
{2F1384C1-9596-FFB7-63CC-02D250E62355}.Release|Any CPU.Build.0 = Release|Any CPU
293+
{2F1384C1-9596-FFB7-63CC-02D250E62355}.Release|x64.ActiveCfg = Release|Any CPU
294+
{2F1384C1-9596-FFB7-63CC-02D250E62355}.Release|x64.Build.0 = Release|Any CPU
295+
{2F1384C1-9596-FFB7-63CC-02D250E62355}.Release|x86.ActiveCfg = Release|Any CPU
296+
{2F1384C1-9596-FFB7-63CC-02D250E62355}.Release|x86.Build.0 = Release|Any CPU
269297
EndGlobalSection
270298
GlobalSection(SolutionProperties) = preSolution
271299
HideSolutionNode = FALSE
@@ -288,6 +316,8 @@ Global
288316
{251A7F28-0166-49BB-AC4C-F72004FE14CC} = {056C07B9-CAD5-4F92-8A24-FBDFDCBA0DDD}
289317
{47696446-67B1-4011-AF4F-AC742A60C7F6} = {056C07B9-CAD5-4F92-8A24-FBDFDCBA0DDD}
290318
{AD9FB993-5657-464E-A3B4-D8163F1AF7C4} = {B73801C2-972F-48CD-A47A-87A4544953E2}
319+
{545E23F2-220C-3065-196C-3956BD778A1C} = {B73801C2-972F-48CD-A47A-87A4544953E2}
320+
{2F1384C1-9596-FFB7-63CC-02D250E62355} = {056C07B9-CAD5-4F92-8A24-FBDFDCBA0DDD}
291321
EndGlobalSection
292322
GlobalSection(ExtensibilityGlobals) = postSolution
293323
SolutionGuid = {7573ED42-AA91-4C5A-8355-F60D23EC57B1}

src/Serilog.Sinks.InMemory.Assertions/InMemorySinkExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ private static bool IsAwesomeAssertionsAlreadyLoadedIntoDomain(
133133
.CurrentDomain
134134
.GetAssemblies()
135135
.FirstOrDefault(assembly =>
136-
assembly.GetName().Name.Equals("FluentAssertions") &&
136+
(assembly.GetName().Name.Equals("FluentAssertions") || assembly.GetName().Name.Equals("AwesomeAssertions")) &&
137137
assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
138138
.Any(metadata => metadata.Value.Contains("AwesomeAssertions", StringComparison.OrdinalIgnoreCase)));
139139

src/Serilog.Sinks.InMemory.Assertions/Serilog.Sinks.InMemory.Assertions.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@
8686
<OutputItemType>Content</OutputItemType>
8787
<PackagePath>lib/$(TargetFramework)</PackagePath>
8888
</ProjectReference>
89+
<ProjectReference Include="..\Serilog.Sinks.InMemory.AwesomeAssertions9\Serilog.Sinks.InMemory.AwesomeAssertions9.csproj">
90+
<ReferenceOutputAssembly>False</ReferenceOutputAssembly>
91+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
92+
<Package>true</Package>
93+
<OutputItemType>Content</OutputItemType>
94+
<PackagePath>lib/$(TargetFramework)</PackagePath>
95+
</ProjectReference>
8996
<ProjectReference Include="..\Serilog.Sinks.InMemory.Shouldly4\Serilog.Sinks.InMemory.Shouldly4.csproj">
9097
<ReferenceOutputAssembly>False</ReferenceOutputAssembly>
9198
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
using System.Linq;
2+
using AwesomeAssertions.Execution;
3+
using AwesomeAssertions.Primitives;
4+
using Serilog.Sinks.InMemory.Assertions;
5+
6+
namespace Serilog.Sinks.InMemory.AwesomeAssertions9
7+
{
8+
public class InMemorySinkAssertionsImpl : ReferenceTypeAssertions<InMemorySink, InMemorySinkAssertionsImpl>, InMemorySinkAssertions
9+
{
10+
public InMemorySinkAssertionsImpl(InMemorySink snapshotInstance) : base(snapshotInstance, AssertionChain.GetOrCreate())
11+
{
12+
}
13+
14+
/*
15+
* Hack attack.
16+
*
17+
* This is a bit of a dirty way to work around snapshotting the InMemorySink instance
18+
* to ensure that you won't get hit by an InvalidOperationException when calling
19+
* HaveMessage() and the logger gets called from somewhere else and adds a new
20+
* LogEvent to the collection while that method is invoked.
21+
*
22+
* For now we copy the LogEvents from the current sink and use reflection to assign
23+
* it to a new instance of InMemorySink that will be used by the assertions,
24+
* effectively creating a snapshot of the InMemorySink that was used by the tests.
25+
*/
26+
private static InMemorySink SnapshotOf(InMemorySink instance)
27+
{
28+
return instance.Snapshot();
29+
}
30+
31+
protected override string Identifier => nameof(InMemorySink);
32+
33+
public LogEventsAssertions HaveMessage(
34+
string messageTemplate,
35+
string because = "",
36+
params object[] becauseArgs)
37+
{
38+
var matches = Subject
39+
.LogEvents
40+
.Where(logEvent => logEvent.MessageTemplate.Text == messageTemplate)
41+
.ToList();
42+
43+
CurrentAssertionChain
44+
.BecauseOf(because, becauseArgs)
45+
.ForCondition(matches.Any())
46+
.FailWith(
47+
"Expected message {0} to be logged",
48+
messageTemplate);
49+
50+
return new LogEventsAssertionsImpl(messageTemplate, matches, CurrentAssertionChain);
51+
}
52+
53+
public PatternLogEventsAssertions HaveMessage()
54+
{
55+
return new PatternLogEventsAssertionsImpl(Subject.LogEvents, CurrentAssertionChain);
56+
}
57+
58+
public void NotHaveMessage(
59+
string messageTemplate = null,
60+
string because = "",
61+
params object[] becauseArgs)
62+
{
63+
int count;
64+
string failureMessage;
65+
66+
if (messageTemplate != null)
67+
{
68+
count = Subject
69+
.LogEvents
70+
.Count(logEvent => logEvent.MessageTemplate.Text == messageTemplate);
71+
72+
failureMessage = $"Expected message \"{messageTemplate}\" not to be logged, but it was found {(count > 1 ? $"{count} times" : "once")}";
73+
}
74+
else
75+
{
76+
count = Subject
77+
.LogEvents
78+
.Count();
79+
80+
failureMessage = $"Expected no messages to be logged, but found {(count > 1 ? $"{count} messages" : "message")}";
81+
}
82+
83+
CurrentAssertionChain
84+
.BecauseOf(because, becauseArgs)
85+
.ForCondition(count == 0)
86+
.FailWith(failureMessage);
87+
}
88+
}
89+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System;
2+
using AwesomeAssertions;
3+
using AwesomeAssertions.Execution;
4+
using AwesomeAssertions.Primitives;
5+
using Serilog.Events;
6+
using Serilog.Sinks.InMemory.Assertions;
7+
8+
namespace Serilog.Sinks.InMemory.AwesomeAssertions9
9+
{
10+
public class LogEventAssertionImpl : ReferenceTypeAssertions<LogEvent, LogEventAssertionImpl>, LogEventAssertion
11+
{
12+
private readonly string _messageTemplate;
13+
14+
public LogEventAssertionImpl(string messageTemplate, LogEvent subject, AssertionChain assertionChain) : base(subject, assertionChain)
15+
{
16+
_messageTemplate = messageTemplate;
17+
}
18+
19+
protected override string Identifier => "log event";
20+
21+
public LogEventPropertyValueAssertions WithProperty(string name, string because = "", params object[] becauseArgs)
22+
{
23+
if (name.StartsWith("@"))
24+
{
25+
name = name.Substring(1);
26+
}
27+
28+
CurrentAssertionChain
29+
.BecauseOf(because, becauseArgs)
30+
.ForCondition(Subject.Properties.ContainsKey(name))
31+
.FailWith("Expected message {0} to have a property {1} but it wasn't found",
32+
_messageTemplate,
33+
name);
34+
35+
return new LogEventPropertyValueAssertionsImpl(
36+
this,
37+
Subject.Properties[name],
38+
name);
39+
}
40+
41+
public LogEventAssertion WithLevel(LogEventLevel level, string because = "", params object[] becauseArgs)
42+
{
43+
CurrentAssertionChain
44+
.BecauseOf(because, becauseArgs)
45+
.ForCondition(Subject.Level == level)
46+
.FailWith("Expected message {0} to have level {1}, but it is {2}",
47+
_messageTemplate,
48+
level.ToString(),
49+
Subject.Level.ToString());
50+
51+
return this;
52+
}
53+
54+
public void Match(Func<LogEvent, bool> predicate)
55+
{
56+
Subject.Should().Match<LogEvent>(o => predicate(o));
57+
}
58+
}
59+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
using System;
2+
using AwesomeAssertions.Primitives;
3+
using Serilog.Events;
4+
using Serilog.Sinks.InMemory.Assertions;
5+
6+
namespace Serilog.Sinks.InMemory.AwesomeAssertions9
7+
{
8+
public class LogEventPropertyValueAssertionsImpl : ReferenceTypeAssertions<LogEventPropertyValue, LogEventPropertyValueAssertionsImpl>, LogEventPropertyValueAssertions
9+
{
10+
private readonly LogEventAssertionImpl _logEventAssertion;
11+
12+
public LogEventPropertyValueAssertionsImpl(LogEventAssertionImpl logEventAssertion, LogEventPropertyValue instance, string propertyName)
13+
: base(instance, logEventAssertion.CurrentAssertionChain)
14+
{
15+
_logEventAssertion = logEventAssertion;
16+
Identifier = propertyName;
17+
}
18+
19+
protected override string Identifier { get; }
20+
21+
public TValue WhichValue<TValue>()
22+
{
23+
if (Subject is ScalarValue scalarValue)
24+
{
25+
CurrentAssertionChain
26+
.ForCondition(scalarValue.Value is TValue)
27+
.FailWith("Expected property value to be of type {0} but found {1}",
28+
typeof(TValue).Name,
29+
scalarValue.Value.GetType().Name);
30+
31+
return (TValue)scalarValue.Value;
32+
}
33+
34+
throw new Exception($"Expected property value to be of type {typeof(TValue).Name} but the property value is not a scalar and I don't know how to handle that");
35+
}
36+
37+
public LogEventAssertion WithValue(object value, string because = "", params object[] becauseArgs)
38+
{
39+
var actualValue = GetValueFromProperty(Subject);
40+
41+
CurrentAssertionChain
42+
.BecauseOf(because, becauseArgs)
43+
.ForCondition(Equals(actualValue, value))
44+
.FailWith("Expected property {0} to have value {1} but found {2}",
45+
Identifier,
46+
value,
47+
actualValue);
48+
49+
return _logEventAssertion;
50+
}
51+
52+
private object GetValueFromProperty(LogEventPropertyValue instance)
53+
{
54+
switch(instance)
55+
{
56+
case ScalarValue scalarValue:
57+
return scalarValue.Value;
58+
default:
59+
return Subject.ToString();
60+
}
61+
}
62+
63+
public StructuredValueAssertions HavingADestructuredObject(string because = "", params object[] becauseArgs)
64+
{
65+
CurrentAssertionChain
66+
.BecauseOf(because, becauseArgs)
67+
.ForCondition(Subject is StructureValue)
68+
.FailWith("Expected message \"{0}\" to have a property {1} that holds a destructured object but found a scalar value",
69+
_logEventAssertion.Subject.MessageTemplate,
70+
Identifier);
71+
72+
return new StructuredValueAssertionsImpl(Subject as StructureValue, Identifier, _logEventAssertion);
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)