Skip to content

Commit

Permalink
Introduce WhichValue<T> method to more easily assert on log property …
Browse files Browse the repository at this point in the history
…values
  • Loading branch information
sandermvanvliet committed May 12, 2021
1 parent e64d481 commit ea1df49
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 3 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,24 @@ InMemorySink.Instance

> **Note:** `WithValue` takes an array of values.
Sometimes you might want to use assertions like `BeLessThanOrEqual()` or `HaveLength()` and in those cases `WithValue` is not very helpful.
Instead you can use `WhichValue<T>()` to access the value of the log property:

```csharp
InMemorySink.Instance
.Should()
.HaveMessage()
.Appearing().Once()
.WithProperty("PropertyOne")
.WhichValue<string>()
.Should()
.HaveLength(3);
```

If the type of the value of the log property does not match the generic type parameter the `WhichValue<T>` method will throw an exception.

> **Note:** This only works for scalar values. When you pass an object as the property value when logging a message Serilog converts that into a string.
## Clearing log events between tests

Depending on your test framework and test setup you may want to ensure that the log events captured by the `InMemorySink` are cleared so tests
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using FluentAssertions;
using System;
using FluentAssertions;
using FluentAssertions.Execution;
using FluentAssertions.Primitives;
using Serilog.Events;
Expand All @@ -18,6 +19,22 @@ public LogEventPropertyValueAssertions(LogEventAssertion logEventAssertion, LogE

protected override string Identifier { get; }

public TValue WhichValue<TValue>()
{
if (Subject is ScalarValue scalarValue)
{
Execute.Assertion
.ForCondition(scalarValue.Value is TValue)
.FailWith("Expected property value to be of type {0} but found {1}",
typeof(TValue).Name,
scalarValue.Value.GetType().Name);

return (TValue)scalarValue.Value;
}

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");
}

public AndConstraint<LogEventAssertion> WithValue(object value, string because = "", params object[] becauseArgs)
{
var actualValue = GetValueFromProperty(Subject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

<PropertyGroup>
<IsPackable>true</IsPackable>
<Version>0.7.0</Version>
<Version>0.8.0</Version>
<Title>Serilog in-memory sink assertion extensions</Title>
<Description>FluentAssertions extensions to use with the Serilog.Sinks.InMemory package</Description>
<Copyright>2020 Sander van Vliet</Copyright>
<Copyright>2021 Sander van Vliet</Copyright>
<Authors>Sander van Vliet</Authors>
<PackageProjectUrl>https://github.com/sandermvanvliet/SerilogSinksInMemory/</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/sandermvanvliet/SerilogSinksInMemory/LICENSE</PackageLicenseUrl>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,5 +140,55 @@ public void GivenLogMessageWithTwoProperties_BothPropertiesExistOnLogEntry()
.WithProperty("PropertyTwo")
.WithValue("two");
}

[Fact]
public void GivenLogMessageWithIntegerProperty_CanAssertUsingFluentAssertions()
{
_logger.Information("{PropertyOne}", 5);

InMemorySink.Instance
.Should()
.HaveMessage()
.Appearing().Once()
.WithProperty("PropertyOne")
.WhichValue<int>()
.Should()
.BeLessOrEqualTo(10);
}

[Fact]
public void GivenLogMessageWithStringProperty_CanAssertUsingFluentAssertions()
{
_logger.Information("{PropertyOne}", "bar");

InMemorySink.Instance
.Should()
.HaveMessage()
.Appearing().Once()
.WithProperty("PropertyOne")
.WhichValue<string>()
.Should()
.HaveLength(3);
}

[Fact]
public void GivenLogMessageWithStringPropertyAndAssertingOnInt_AssertionFailsBecauseOfTypeMismatch()
{
_logger.Information("{PropertyOne}", "bar");

Action action = () => InMemorySink.Instance
.Should()
.HaveMessage()
.Appearing().Once()
.WithProperty("PropertyOne")
.WhichValue<int>()
.Should()
.BeLessThan(3);

action
.Should()
.Throw<Exception>()
.WithMessage($"Expected property value to be of type \"{nameof(Int32)}\" but found \"{nameof(String)}\"");
}
}
}

0 comments on commit ea1df49

Please sign in to comment.