Question

I am trying to find the most fluent manner to assert that a certain string is a valid Guid.

iterTags.GUID is a string.

My first attempt ended in error because stringdoes not implement Guid. Okay, I saw it coming as it was a shot in the dark

iterTags.GUID.Should().BeAssignableTo<Guid>();

So i came up with this working solution but it's not fluent

Guid parsedGuid;
if (!Guid.TryParseExact(iterTags.GUID, "D", out parsedGuid))
    Assert.Fail("iterTags.GUID: '{0}' is not a valid guid");

Reading the documentation I found no better way of doing the assertion.

My question: Is there a fluent way of asserting a string is a valid Guid

Perhaps, something like...

iterTags.GUID.Should().BeParsedAs<Guid>()
Was it helpful?

Solution

Guid parsedGuid;
Guid.TryParseExact(iterTags.GUID, "D", out parsedGuid).Should.BeTrue("because {0} is a valid Guid string representation", iterTags.GUID);

or

new Action(() => new Guid(iterTags.GUID)).ShouldNotThrow("because {0} is a valid Guid string representation", iterTags.GUID);

OTHER TIPS

You could also use the not be empty check on a GUID, that way you can use FluentAssertions's empty checking:

Guid.TryParse(iterTags.GUID, out var parsedIterTagsGUID)
parsedIterTagsGUID.Should().NotBeEmpty();

Or as extension:

    public static AndConstraint<FluentAssertions.Primitives.GuidAssertions> ShouldBeGuid(this object value, string because = "", params object[] becauseArgs)
    {
        Guid.TryParse(value?.ToString(), out var guid);
        return guid.Should().NotBeEmpty(because, becauseArgs);
    }

The above can be done better, by extending something else like:

    public static AndConstraint<GuidAssertions> BeGuid(this StringAssertions value, string because = "", params object[] becauseArgs)
    {
        Guid.TryParse(value.Subject, out var guid);
        return guid.Should().NotBeEmpty(because, becauseArgs);
    }

    public static AndConstraint<GuidAssertions> BeGuid(this ObjectAssertions value, string because = "", params object[] becauseArgs)
    {
        return (value.Subject as Guid?).Should().NotBeNull().And.NotBeEmpty(because, becauseArgs);
    }

Or maybe even better by proposing a pull request on: https://github.com/fluentassertions/fluentassertions

Here's what I ended up going with, inspired by Nick N's answer.

The main difference is that the failure message is clearer about the string not being a GUID, where the NotBeEmpty condition would return a message saying that the input is empty.

public static class CustomAssertions
{
    public static AndConstraint<StringAssertions> BeGuid(this StringAssertions assertions, string because = "", params object[] becauseArgs)
    {
        var isGuid = Guid.TryParse(assertions.Subject, out _);

        Execute.Assertion
           .ForCondition(isGuid)
           .BecauseOf(because, becauseArgs)
           .FailWith("Expected a GUID converted to a string{reason}, but found {0}.", assertions.Subject);

        return new AndConstraint<StringAssertions>(assertions);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top