Skip to content

Commit

Permalink
Merge pull request #1208 from jnyrup/enum_equality
Browse files Browse the repository at this point in the history
Fix comparing enums and integers for equality
  • Loading branch information
jnyrup committed Jan 1, 2020
2 parents 787e616 + 734e3e7 commit 7b01b24
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 5 deletions.
20 changes: 15 additions & 5 deletions Src/FluentAssertions/Common/ObjectExtensions.cs
@@ -1,5 +1,6 @@
using System;
using System.Globalization;
using System.Reflection;

namespace FluentAssertions.Common
{
Expand Down Expand Up @@ -31,8 +32,8 @@ public static bool IsSameOrEqualTo(this object actual, object expected)
Type actualType = actual.GetType();

return actualType != expectedType
&& IsNumericType(actual)
&& IsNumericType(expected)
&& (actual.IsNumericType() || actualType.IsEnumType())
&& (expected.IsNumericType() || expectedType.IsEnumType())
&& CanConvert(actual, expected, actualType, expectedType)
&& CanConvert(expected, actual, expectedType, actualType);
}
Expand All @@ -41,9 +42,9 @@ private static bool CanConvert(object source, object target, Type sourceType, Ty
{
try
{
var converted = Convert.ChangeType(source, targetType, CultureInfo.InvariantCulture);
var converted = source.ConvertTo(targetType);

return source.Equals(Convert.ChangeType(converted, sourceType, CultureInfo.InvariantCulture))
return source.Equals(converted.ConvertTo(sourceType))
&& converted.Equals(target);
}
catch
Expand All @@ -53,7 +54,14 @@ private static bool CanConvert(object source, object target, Type sourceType, Ty
}
}

private static bool IsNumericType(object obj)
private static object ConvertTo(this object source, Type targetType)
{
return IsEnumType(targetType)
? Enum.ToObject(targetType, source)
: Convert.ChangeType(source, targetType, CultureInfo.InvariantCulture);
}

private static bool IsNumericType(this object obj)
{
switch (obj)
{
Expand All @@ -73,5 +81,7 @@ private static bool IsNumericType(object obj)
return false;
}
}

private static bool IsEnumType(this Type type) => type.GetTypeInfo().IsEnum;
}
}
35 changes: 35 additions & 0 deletions Tests/Shared.Specs/EnumAssertionSpecs.cs
Expand Up @@ -97,5 +97,40 @@ public void When_expectation_is_null_and_subject_enum_has_some_value_it_should_t
act.Should().Throw<XunitException>()
.WithMessage("Expected*to be <null> because comparing enums should throw, but found UInt64Max*");
}

// TODO: should probably fail in 6.0, see #1204
[Fact]
public void When_comparing_an_enum_and_a_numeric_for_equality_it_should_not_throw()
{
// Arrange
MyEnum subject = MyEnum.One;
object expected = 1;

// Act
Action act = () => subject.Should().Be(expected);

// Assert
act.Should().NotThrow();
}

// TODO: should probably fail in 6.0, see #1204
[Fact]
public void When_comparing_a_numeric_and_an_enum_for_equality_it_should_not_throw()
{
// Arrange
object subject = 1;
MyEnum expected = MyEnum.One;

// Act
Action act = () => subject.Should().Be(expected);

// Assert
act.Should().NotThrow();
}

private enum MyEnum
{
One = 1
}
}
}

0 comments on commit 7b01b24

Please sign in to comment.