More strange and unexpected behavior from Visual Studio Team System (VSTS)... This time I'm experiencing a problem with unit testing. I have a solution although it seems more like a workaround to me, and I haven't been able to find out the exact root of the problem. Here's the story.
I have a custom class, let's call it Customer (name changed to protect the class' privacy). This class is derived from another custom generic container class. I've implemented Equals, GetHashCode, and the == and != operators on it. These are necessary because of the class' heritage: it has to make sure that, when comparing two instances, these two instances have identical elements in their collections. So far, so good.
However, a unit test which creates two identical Customers and then compares them, fails on the following line:
Assert.AreEqual(a, b, "Equality");
(the string being a message to display in case the test fails.)
Close on-location examination of the facts revealed the startling truth that a and b were, in fact identical... But surely something must have gone wrong. After more examination, detective work, interrogations etc. I decided to try something else:
Assert.IsTrue(a == b, "Equality");
Miraculously, this worked. Did this prove that the objects were indeed equal? I added some more tests to make sure.
Assert.IsTrue(b == a, "Equality 2");
Assert.IsTrue(a.Equals(b), "Equality 3");
Assert.IsTrue(b.Equals(a), "Equality 4");
And yes, these tests passed too. So why not Assert.AreEqual()??
My mole at Microsoft was stumped. He asked if I had done an inside examination of Assert.AreEqual() with Reflector. Turns out I hadn't, so I cranked it up.
That revealed that Assert.AreEqual() depends on object.Equals() to determine equality. But then examination of object.Equals() showed that it first tries to use the == operator, and if that fails, it tries to use the object's Equals implementation.
This would seem to suggest that Assert.AreEqual() is off the hook and that the problem should actually never appear. But it also suggests that object.Equals() doesn't always use the objects' own == or Equals implementation. How else can we explain why the other tests, as shown above, all work while the AreEqual test fails? This is corroborated by the fact that code coverage testing in Visual Studio shows that the object's own Equals and == implementations are not executed by AreEqual.
My workaround solution is simple: to not use Assert.AreEqual whenever it poses a problem. After all, the code that is being tested is always going to be used with the Equals and the == and != operators, so replacing AreEqual() with IsTrue(==) etc. seems like a natural thing to do. But I do like the syntactic sugar of AreEqual, and it bugs me that I don't understand why this is a problem.
Do you know what's going on? Hey, guys in the VSTS team (Jonathan! James!), what's the story here?
It's surprising to me that, so far, I haven't been able to find any blog entry or article anywhere about why the Visual Studio 2005 Code Coverage tool doesn't handle C#'s switch statement properly.
I use switch a lot, because it's so much easier to read than lots of if/else ifs, but the fact is any function in my code that contains switch gets marked, after complete and utter unit-testing, as not having been covered 100% -- there's always one block counted as being untested. Yet every line of code in that function is marked nicely in light blue, indicating that it was run. The unit test code makes sure that all cases are covered...
Then when I rewrite the code to use if/else if/... instead of switch, coverage is 100%.
Duh! I want to keep using switch!