Search code examples
c#unit-testingfluent-assertions

FluentAssertions: how to set breakpoint inside lambda


FluentAssertions is a great library but often I am very frustrated when some code in lambda is not working as expected and I cannot debug it. Especially when lambda is complicated.

payload.Resource.Relations.Removed.Should().NotBeNull()
            .And.HaveCount(2)
            .And.AllBeOfType<ResourceRelation>()
            .And.OnlyContain(rel => 
    rel.RelationType.MatchTo(RelationType.ArtifactLink) && 
    rel.Href.AbsoluteUri.StartsWith(VsTfsSchema.GitPullRequestId));

In this case, I would like to set a breakpoint into inside OnlyContain(...) lambda and debug it. But this is not possible - breakpoint is set always at the whole statement. I suppose that the reason is that lambdas in FluentAssertions are expressions.

Is there any way how to achieve this?

Edit: Extracting lambda as local variable does not help. Behavior is the same.

System.Linq.Expressions.Expression<Func<ResourceRelation, bool>> predicate = rel =>
            rel.RelationType.MatchTo(RelationType.ArtifactLink) && rel.Href.AbsoluteUri.StartsWith(VsTfsSchema.GitPullRequestId);

payload.Resource.Relations.Removed.Should().NotBeNull()
    .And.HaveCount(2)
    .And.AllBeOfType<ResourceRelation>()
    .And.OnlyContain(predicate);

Edit2: Here is really simple and verifiable example. You cannot put a breakpoint into num == 1, nor extract it as local function, nor display it at watch.

[Fact]
public void SimpleLambdaTest()
{
    int[] nums = Enumerable.Range(1, 10).ToArray();
    nums.Should().OnlyContain(num => num == 1);
}

Solution

  • You can extract the expression body into a static function, in which you can set a breakpoint.

    Note that EqualsOne cannot be a local function and cannot be passed as a method group.

    [Fact]
    public void SimpleLambdaTest()
    {
        int[] nums = Enumerable.Range(1, 10).ToArray();
        nums.Should().OnlyContain(num => EqualsOne(num));
    }
    
    private static bool EqualsOne(int num)
    {
        // You can put a break point here
        return num == 1;
    }