1

Suppose i have lots of classes like this (Foo1, Foo2 ..)

class Foo 
{
    public int F{get; set;}

    public Bar ConvertToBar ()
    {
        return new Bar(){ B = this.F*10 };
    }
}

all they have in common is ConvertToBar() method.

I have two approaches to unit-test this method:

  1. Call convert to ConvertToBar () and check all it's properties (I have to do it in all tests for each Foo like class)

    Bar bar = foo.ConvertToBar (); Assert.AreEqual (expectedValue, bar.Property); ...

  2. Write helper method that compares two Bar instances and then use it like this:

    Bar expectedBar = new Bar () Assert.True( barCompareMethod (expectedBar, foo.ConvertToBar ());

What will be the best way to write unit-test for this method?

Nick
  • 25,026
  • 7
  • 51
  • 83
Denis Palnitsky
  • 18,267
  • 14
  • 46
  • 55
  • Related: http://stackoverflow.com/questions/2046121/how-to-compare-two-object-in-unit-test-how-to-compare-two-collection-in-unit-tes – Mark Seemann Apr 20 '11 at 14:09

3 Answers3

4

Does it make sense for Bar itself to be IEquatable<Bar>? If so, I'd implement that in your production code, rather than having a helper method. Then you can just use Assert.AreEqual(expectedBar, actualBar).

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • And, what do you think about if it makes sense the effort of implementing `IEquatable` in all classes subject of testing conversions? It'd be a nightmare! – Matías Fidemraizer Apr 20 '11 at 14:08
  • +1 I always go for IEquatable myself, but see my answer for how to handle cases where that isn't appropriate or possible. – Mark Seemann Apr 20 '11 at 14:09
  • @Orsol: Then implementing `IEqualityComparer` would make sense - or possibly just creating a helper method, as you suggest. In fact, the helper method could be an AssertBarEquals method that would indicate where they differed. – Jon Skeet Apr 20 '11 at 14:11
  • 1
    @Matías: Well, it's the target of the conversions that's important here... and the OP says he's only got one target type. I find that the targets of conversions are typically the kinds of type where it's useful to have equality anyway. – Jon Skeet Apr 20 '11 at 14:14
  • @Jon Skeet I'm agreed, it's just an advice for the author because maybe this is a limited example and he needs to think what's going on if it takes 'IEquatable' approach :) – Matías Fidemraizer Apr 20 '11 at 14:21
4

As Jon Skeet suggests, implementing custom equality on Bar is a great idea as long as you understand how to steer clear of Equality Pollution.

For semantic comparison, you can use AutoFixture's SemanticComparison library, which would enable you to write a assertion like this:

var expected = bar1.AsSource().OfLikeness<Bar>();
expected.ShouldEqual(bar2);

The ShouldEqual method is a custom assertion that will compare each property (matched by name) and only succeed when all properties are equal; otherwise it will throw a descriptive exception.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
3

I'm not sure there is a best way.

  • the first is a bit more readable in my opinion. You may want to experiment with NUnit's property constaints

    Assert.That(someObject, Has.Property("Version").EqualTo("2.0"));

  • the second is a bit more work in that you'd have to define Equals in the Bar classes (might be a problem if you do not have source edit access). But it would be preferable, if a large number of properties need to be asserted on.

Gishu
  • 134,492
  • 47
  • 225
  • 308
  • Personally I find that for performing a simple equality test, the property constraint is much less readable than a simple Assert.AreEqual test. I know some people love it, but I'm not a fan myself... – Jon Skeet Apr 20 '11 at 14:14
  • @Jon - True. I was answering to the example in the Question. If an object has n properties, out of which only 1 or 2 are relevant in the context of the current test, I prefer constraints or matchers because they tend to highlight the change. If a majority of the properties are relevant, then I agree that the equality method approach wins.. I'm experimenting with Hamcrest matchers as of now.. so might be posting under the influence :) – Gishu Apr 20 '11 at 15:26
  • I was meaning a simple `Assert.AreEqual("2.0", someObject.Version)` instead of using the `Has.Property` syntax. I've never been much of a fan of Hamcrest either ;) – Jon Skeet Apr 20 '11 at 15:31
  • @Jon - To quote Homer simpson "DOH!" :) I just instantly lost faith in Has.Property.. even `AssertThat(someObject.Version, Equals("2.0"))` is better. – Gishu Apr 21 '11 at 05:34