-
-
Save JayBazuzi/ffb7daa9450b2a647302 to your computer and use it in GitHub Desktop.
| static class ValueTypeAssertions | |
| { | |
| class C | |
| { | |
| } | |
| /// <summary> | |
| /// Asserts that this type correctly implements "value" equality semantics. | |
| /// </summary> | |
| /// <param name="a">An example of T</param> | |
| /// <param name="aPrime">Another T which should be the "same" as a</param> | |
| /// <param name="b">Another T which should be different from a</param> | |
| public static void HasValueEquality<T>(T a, T aPrime, T b) | |
| { | |
| Assert.IsTrue(a.Equals(aPrime)); | |
| Assert.IsTrue(a.GetHashCode().Equals(aPrime.GetHashCode())); | |
| Assert.IsFalse(a.Equals(b)); | |
| Assert.IsFalse(a.GetHashCode().Equals(b.GetHashCode())); | |
| Assert.IsFalse(a.Equals(null)); | |
| Assert.IsFalse(a.Equals(new C())); | |
| Assert.AreEqual(a, aPrime); | |
| Assert.AreNotEqual(a, b); | |
| } | |
| } |
I often want to create small types with "value" equality semantics, as opposed to reference equality. C# makes me write a bunch of boilerplate code each time, but that doesn't mean I should have to write the same boilerplate tests. Instead, I want a single simple test that says "Assert that my type has value equality".
Then Should().Be() should work. It uses Object.Equals under the hood.
There's nothing wrong with Should().Be(), but I want the whole assert you see above.
a.ShouldHaveValueEquality(anotherA, b); // asserts those 7 things
So it should assert that Equals returns true and GetHashCode returns the same value for both objects?
It should assert the 7 things listed in my Gist.
Just forked and made the boilerplate to create a, aPrime, b less cumbersome. Next steps I think would be to create rich error messaging by either integrating with FluentAssertions or creating good messages with these asserts. I also think we may want to add an Assert to make sure it inherits from IEquatable.
I see that, but FA usually takes two objects and executes an assertion on that, but your gist uses 4 objects. Value Equality in .NET means that two objects return true for Equals, return the same value for GetHashCode even though ReferenceEquals returns false. I could have an extension method that takes a factory lamba like @bgeihsgt just showed.
@bgeihsgt and @dennisdoomen: Here's another iteration. I split out equality from inequality, so you can deal with case-insensitive stuff:
new Foo("bar")should equalnew Foo("BAR")
So what's so special about this example that Fluent Assertions'
a.Should().Be(aPrime)doesn't do? The GetHashCode()?