5

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>()
Luis Filipe
  • 8,488
  • 7
  • 48
  • 76

3 Answers3

3
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);
Max Yakimets
  • 1,195
  • 7
  • 12
  • Great solution. I just needed to explicitly create an Action: new Action(() => new Guid(iterTags.GUID)).ShouldNotThrow(""); – Luis Filipe Jan 23 '14 at 12:59
  • would you care to correct your second solution (or tell me i am wrong if it compiles in your VS) – Luis Filipe Jan 23 '14 at 13:02
  • sure. I do not have the Fluent Assertions installed, just got interested and read through the documentation :) – Max Yakimets Jan 23 '14 at 13:04
  • another option could be to write an extension - but that would certainly require Fluent Assertions be referenced to test the code. – Max Yakimets Jan 23 '14 at 13:06
  • I do have it referenced so that would not be the problem. I should have seen the correct portion of the documentation but, honestly, did not understand it as i should - well paving the road for a better human :) thanks – Luis Filipe Jan 23 '14 at 13:07
  • Creating an extension is no big deal. It's just that, an extension method. The only thing FA adds is some plumbing to get some nice messages. See the extensibility section here https://github.com/dennisdoomen/fluentassertions/wiki/Documentation#wiki-extensibility – Dennis Doomen Jan 26 '14 at 15:05
3

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

Nick N.
  • 12,902
  • 7
  • 57
  • 75
2

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);
    }
}
Sam Jones
  • 4,443
  • 2
  • 40
  • 45