Skip to content

Regression in 4.3.0 comparing class that override equals and implicit string conversion #4902

@alkampfergit

Description

@alkampfergit

This is the code that shows the bug, both tests passes in Nunit 4.1 (correctly) but with nunit 4.3 the first test does not pass.

Error is in EqualStringWithoutUsingConstraint, because since the class is implicitly convertible as string, it consider as string but actually in the ApplyTo the code does actual as string that clearly does not trigger the implicit operator resulting in a failure..

image

Here is a simple file that shows the error, both test passes in the 4.1 version of the driver, the first one is red in the 4.3 version of the driver (we have almost 400 test that incorrectly fails in our test suite due to this problem :) ).

Also casting explicitly as (object) remove the ambiguity because the correct Is.EqualTo is called, if you correctly determine that you want to use a EqualStringConstraint the object passed must be casted as string with (string) syntax not with the "as string" syntax.

using NUnit.Framework;

namespace NunitTest;

[TestFixture]
public class Fixture
{
    [Test]
    public void Test_Bugged()
    {
        TestClass testClass = new TestClass(1);
        TestClass testClassOther = new TestClass(1);
        Assert.That(testClassOther, Is.EqualTo(testClass));
    }
    [Test]
    public void Test_ok_explicit_caset()
    {
        TestClass testClass = new TestClass(1);
        TestClass testClassOther = new TestClass(1);
        Assert.That(testClassOther, Is.EqualTo((object) testClass));
    }
    [Test]
    public void Test_Ok()
    {
        TestClass testClass = new TestClass(1);
        TestClass testClassOther = new TestClass(1);

        //This is ok
        Assert.That(testClassOther.AsString(), Is.EqualTo(testClass.AsString()));
    }
}

public class TestClass 
{
    private string _id;

    public TestClass(int number)
    {
        _id = "Test_" + number;
    }

    public override string ToString()
    {
        return _id;
    }

    public static implicit operator string(TestClass testClass)
    {
        return testClass._id;
    }

    public string AsString()
    {
        return _id;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;

        var identity = obj as TestClass;

        if (identity != null)
        {
            return Equals(identity);
        }

        return false;
    }

    public bool Equals(TestClass other)
    {
        if (other != null)
        {
            return other._id.Equals(_id);
        }

        return false;
    }

    public override int GetHashCode()
    {
        return _id.GetHashCode();
    }
}

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions