Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Comparable type assertions referential equality #2046

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
83 changes: 33 additions & 50 deletions Tests/FluentAssertions.Specs/Numeric/ComparableSpecs.cs
Expand Up @@ -21,20 +21,18 @@ public void When_two_instances_are_equal_it_should_succeed()
}

[Fact]
public void When_two_instances_are_the_same_reference_but_are_not_considered_equal_it_should_not_succeed()
public void When_two_instances_are_the_same_reference_but_are_not_considered_equal_it_should_succeed()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 I can't get my head around this one ;-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's quite unlikely that someone would implement a type that is not reflexive.

{
// Arrange
var subject = new SameInstanceIsNotEqualClass();
var other = subject;

// Act
Action act = () => subject.Should().Be(other, "they have the same property values");
Action act = () => subject.Should().Be(other);

// Assert
act
.Should().Throw<XunitException>()
.WithMessage(
"Expected*SameInstanceIsNotEqualClass*because they have the same property values, but found*SameInstanceIsNotEqualClass*.");
act.Should().NotThrow(
"This is inconsistent with the behavior ObjectAssertions.Be but is how ComparableTypeAssertions.Be has always worked.");
}

[Fact]
Expand All @@ -58,7 +56,7 @@ public void When_two_instances_are_not_equal_it_should_throw()
public class NotBe
{
[Fact]
public void When_two_references_to_the_same_instance_are_not_equal_it_should_succeed()
public void When_two_references_to_the_same_instance_are_not_equal_it_should_throw()
{
// Arrange
var subject = new SameInstanceIsNotEqualClass();
Expand All @@ -68,7 +66,8 @@ public void When_two_references_to_the_same_instance_are_not_equal_it_should_suc
Action act = () => subject.Should().NotBe(other);

// Assert
act.Should().NotThrow();
act.Should().Throw<XunitException>(
"This is inconsistent with the behavior ObjectAssertions.Be but is how ComparableTypeAssertions.Be has always worked.");
}

[Fact]
Expand Down Expand Up @@ -106,28 +105,13 @@ public void When_two_unequal_objects_should_not_be_equal_it_should_not_throw()
public class BeOneOf
{
[Fact]
public void When_a_value_is_not_one_of_the_specified_values_it_should_throw()
public void When_a_value_is_not_equal_to_one_of_the_specified_values_it_should_throw()
{
// Arrange
var value = new ComparableOfInt(3);
var value = new EquatableOfInt(3);

// Act
Action act = () => value.Should().BeOneOf(new ComparableOfInt(4), new ComparableOfInt(5));

// Assert
act
.Should().Throw<XunitException>()
.WithMessage("Expected value to be one of {4, 5}, but found 3.");
}

[Fact]
public void When_a_value_is_not_one_of_the_specified_values_it_should_throw_with_descriptive_message()
{
// Arrange
var value = new ComparableOfInt(3);

// Act
Action act = () => value.Should().BeOneOf(new[] { new ComparableOfInt(4), new ComparableOfInt(5) }, "because those are the valid values");
Action act = () => value.Should().BeOneOf(new[] { new EquatableOfInt(4), new EquatableOfInt(5) }, "because those are the valid {0}", "values");

// Assert
act
Expand All @@ -136,28 +120,28 @@ public void When_a_value_is_not_one_of_the_specified_values_it_should_throw_with
}

[Fact]
public void When_a_value_is_comparable_to_but_a_different_instance_of_one_of_the_specified_values_it_should_fail()
public void When_two_instances_are_the_same_reference_but_are_not_considered_equal_it_should_succeed()
{
// Arrange
var value = new ComparableOfInt(4);
var subject = new SameInstanceIsNotEqualClass();
var other = subject;

// Act
Action act = () => value.Should().BeOneOf(new ComparableOfInt(4), new ComparableOfInt(5));
Action act = () => subject.Should().BeOneOf(other);

// Assert
act
.Should().Throw<XunitException>()
.WithMessage("Expected value to be one of {4, 5}, but found 4.");
act.Should().NotThrow(
"This is inconsistent with the behavior ObjectAssertions.Be but is how ComparableTypeAssertions.Be has always worked.");
}

[Fact]
public void When_a_value_is_the_same_instance_as_one_of_the_specified_values_it_should_succeed()
public void When_a_value_is_equal_to_one_of_the_specified_values_it_should_succeed()
{
// Arrange
var value = new ComparableOfInt(4);
var value = new EquatableOfInt(4);

// Act
Action act = () => value.Should().BeOneOf(value, new ComparableOfInt(5));
Action act = () => value.Should().BeOneOf(new EquatableOfInt(4), new EquatableOfInt(5));

// Assert
act.Should().NotThrow();
Expand All @@ -171,7 +155,7 @@ public void When_two_instances_are_equivalent_it_should_succeed()
{
// Arrange
var subject = new ComparableCustomer(42);
var expected = new CustomerDTO(42);
var expected = new CustomerDto(42);

// Act / Assert
subject.Should().BeEquivalentTo(expected);
Expand All @@ -182,7 +166,7 @@ public void When_two_instances_are_compared_it_should_allow_chaining()
{
// Arrange
var subject = new ComparableCustomer(42);
var expected = new CustomerDTO(42);
var expected = new CustomerDto(42);

// Act / Assert
subject.Should().BeEquivalentTo(expected)
Expand All @@ -194,7 +178,7 @@ public void When_two_instances_are_compared_with_config_it_should_allow_chaining
{
// Arrange
var subject = new ComparableCustomer(42);
var expected = new CustomerDTO(42);
var expected = new CustomerDto(42);

// Act / Assert
subject.Should().BeEquivalentTo(expected, opt => opt)
Expand All @@ -206,7 +190,7 @@ public void When_two_instances_are_equivalent_due_to_exclusion_it_should_succeed
{
// Arrange
var subject = new ComparableCustomer(42);
var expected = new AnotherCustomerDTO(42)
var expected = new AnotherCustomerDto(42)
{
SomeOtherProperty = 1337
};
Expand All @@ -222,7 +206,7 @@ public void When_injecting_a_null_config_it_should_throw()
{
// Arrange
var subject = new ComparableCustomer(42);
var expected = new AnotherCustomerDTO(42);
var expected = new AnotherCustomerDto(42);

// Act
Action act = () => subject.Should().BeEquivalentTo(expected, config: null);
Expand All @@ -237,7 +221,7 @@ public void When_two_instances_are_not_equivalent_it_should_throw()
{
// Arrange
var subject = new ComparableCustomer(42);
var expected = new AnotherCustomerDTO(42)
var expected = new AnotherCustomerDto(42)
{
SomeOtherProperty = 1337
};
Expand Down Expand Up @@ -686,12 +670,8 @@ public override string ToString()
}
}

public class SameInstanceIsNotEqualClass
public class SameInstanceIsNotEqualClass : IComparable<SameInstanceIsNotEqualClass>
{
public SameInstanceIsNotEqualClass()
{
}

public override bool Equals(object obj)
{
return false;
Expand All @@ -701,6 +681,9 @@ public override int GetHashCode()
{
return 1;
}

int IComparable<SameInstanceIsNotEqualClass>.CompareTo(SameInstanceIsNotEqualClass other) =>
throw new NotSupportedException("This type is meant for assertions using Equals()");
}

public class EquatableOfInt : IComparable<EquatableOfInt>
Expand Down Expand Up @@ -766,19 +749,19 @@ public int CompareTo(ComparableCustomer other)
}
}

public class CustomerDTO
public class CustomerDto
{
public CustomerDTO(int id)
public CustomerDto(int id)
{
Id = id;
}

public int Id { get; }
}

public class AnotherCustomerDTO
public class AnotherCustomerDto
{
public AnotherCustomerDTO(int id)
public AnotherCustomerDto(int id)
{
Id = id;
}
Expand Down
Expand Up @@ -6,8 +6,6 @@
using System.Xml.Serialization;
using FluentAssertions.Execution;
using FluentAssertions.Extensions;
using FluentAssertions.Primitives;
using FluentAssertions.Specs.Numeric;
using Xunit;
using Xunit.Sdk;

Expand Down