joerg
joerg

Reputation: 757

Unit Test: Clone and equality

I am writing Unit Tests and thinking about the scenario of a type that implements IClonable. So of course I want to have a Unit Test that tests the Clone() method.

[Test]
public void CloneObject()
{
    MyType original = new MyType();
    MyType clone = (MyType)original.Clone();

    // Assert for equality
}

So my first task it to have an Assert for the equality. I see following options:

For the first two I can setup my tests and they work well. But what if I change MyType and add an additional property? If Clone() doesn't copy this and I don't add it in the list of checked properties or the equals method my test still passes even if the property does not get copied.

How do you solve this kind of tests?

Upvotes: 5

Views: 3876

Answers (2)

Jeff Prince
Jeff Prince

Reputation: 678

I would favor implementing Equals(). I see no reason why Equals() needs to produce different results in production vs. in tests.

If you don't do that, your Assert could call object.ReferenceEquals(), as follows:

Assert.IsTrue(object.ReferenceEquals(expectedObject, objectInHand));

Upvotes: 1

dcastro
dcastro

Reputation: 68710

You can use the FluentAssertions library (a TDD must-have, IMO), which has a ShouldBeEquivalent method that performs graph comparison of the two objects:

original.ShouldBeEquivalentTo(clone);

The comparison algorithm can be customized via the optional options parameter; see their wiki for detailed info.

To make the test future-proof (i.e., it breaks when new properties are added to the class, but not to the Clone method), you might want to test cloning an object with all its properties set to random non-default values. AutoFixture can do that for you.

// Arrange
var fixture = new Fixture();
var original = fixture.Create<MyType>();

// Act
var clone = original.Clone();

// Assert
clone.ShouldBeEquivalentTo(original);

Useful links:

Upvotes: 7

Related Questions