Skip to content

Asserts with UsingPropertiesComparer and Tolerance crashes unxpectedly if using TimeSpan and the class contains Properties with different types. #4968

Description

@Taron-art

Example:

    [TestFixture]
    public class RepeatTest
    {
        public class ClassToCheck()
        {
            public int Id { get; set; } = 1;
            public string Name { get; set; } = "Name";
            public DateTimeOffset Now { get; } = DateTimeOffset.UtcNow;
        }


        [Test]
        public void Test()
        {
            var expected = new ClassToCheck();
            var actual = new ClassToCheck();
            Assert.That(actual, Is.EqualTo(expected).UsingPropertiesComparer().Within(TimeSpan.FromSeconds(1)));
        }
    }

I expect this test to pass since I'm trying to add a tolerance for DateTime comparison. NUnit, however, tries to apply this tolerance to the int field. As a result, the test fails with the following:

Message: 
  System.InvalidCastException : Unable to cast object of type 'System.TimeSpan' to type 'System.IConvertible'.

Stack Trace: 
  Convert.ToInt32(Object value)
  Numerics.AreEqual(Int32 expected, Int32 actual, Tolerance tolerance)
  Numerics.AreEqual(Object expected, Object actual, Tolerance& tolerance)
  NumericsComparer.Equal(Object x, Object y, Tolerance& tolerance, ComparisonState state, NUnitEqualityComparer equalityComparer)
  NUnitEqualityComparer.AreEqual(Object x, Object y, Tolerance& tolerance, ComparisonState state)
  PropertiesComparer.Equal(Object x, Object y, Tolerance& tolerance, ComparisonState state, NUnitEqualityComparer equalityComparer)
  NUnitEqualityComparer.AreEqual(Object x, Object y, Tolerance& tolerance, ComparisonState state)
  NUnitEqualityComparer.AreEqual(Object x, Object y, Tolerance& tolerance)
  EqualConstraint.ApplyTo[TActual](TActual actual)
  Assert.That[TActual](TActual actual, IResolveConstraint expression, NUnitString message, String actualExpression, String constraintExpression)
  RepeatTest.Test() line 26
  RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
  MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

While I understand why it happened, an expected behavior would be to apply tolerance only to the applicable types. It however opens a rabbit hole (what if I want more than one tolerance for different types?). I still think this is a bug, may be it can be handled with a more user friendly error message.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions