I'm using the excellent Shouldly
library in my xUnit tests and I'm finding myself using the set sequence of assertions in different tests, so I'm combining them into new assertion extension methods - but when I do this I lose Shouldly
's contextual assertion messages.
Here's my old code, which works with Shouldly
to include source-level information and call-site context in the Shouldly
assertion error:
[Fact]
public void Dict_should_contain_valid_Foobar_Bar_entry()
{
IDictionary<String,Bar> dict = ...
dict.TryGetValue( "Foobar", out Bar bar ).ShouldBeTrue();
bar.ShouldNotBeNull();
bar.ChildList.Count.ShouldBe( expected: 3 );
bar.Message.ShouldBeNull();
}
[Fact]
public void Dict_should_contain_valid_Barbaz_Bar_entry()
{
IDictionary<String,Bar> dict = ...
dict.TryGetValue( "Barbaz", out Bar bar ).ShouldBeTrue();
bar.ShouldNotBeNull();
bar.ChildList.Count.ShouldBe( expected: 3 );
bar.Message.ShouldBeNull();
}
I converted it to this new extension method in the same project:
public static void ShouldBeValidBar( this IDictionary<String,Bar> dict, String barName )
{
dict.ShouldNotBeNull();
dict.TryGetValue( barName, out Bar bar ).ShouldBeTrue();
bar.ShouldNotBeNull();
bar.ChildList.Count.ShouldBe( expected: 3 );
bar.Message.ShouldBeNull();
}
And so my tests are changed to this:
[Fact]
public void Dict_should_contain_valid_Foobar_Bar_entry()
{
IDictionary<String,Bar> dict = ...
dict.ShouldBeValidBar( "Foobar" );
}
[Fact]
public void Dict_should_contain_valid_Barbaz_Bar_entry()
{
IDictionary<String,Bar> dict = ...
dict.ShouldBeValidBar( "Barbaz" );
}
...but now my Shouldly assert messages don't contain any contextual information from Dict_should_contain_valid_Foobar_Bar_entry
and instead only contains context from ShouldBeValidBar
.
How can I instruct Shouldly
to disregard the context of ShouldBeValidBar
and to use its parent call-site instead?
[ShouldlyMethods]
on the extension method itself, but it works when I add the attribute to the containing class. – Soot