Hi Patrick,
"a" and "b" point to the same object, but there are different methods being called because of method hiding. I'm not sure if the test should pass because it may be important to distinguish between the methods.
How do you see this working in a real-world scenario where there's
actually a class that implements "A" and "B"?
Let me clarify that in a real-world scenario there should never be code that actually does this. :) However apparently there are libraries around that do. Here is an example that uses a class that implements B (and therefore implements A too). I've slightly modified A and B to make it clearer what's happening:
public interface A { string GetStr(); }
public interface B : A { new string GetStr(); }
public class AB : B {
string A.GetStr() { return "A"; }
string B.GetStr() { return "B"; }
}
[Test]
public void ClassInheritanceHidingStuff() {
var b = (B)new AB();
Assert.That( b.GetStr(), Is.EqualTo("B") );
Assert.That( ((A) b).GetStr(), Is.EqualTo("A") );
}
This passes. So calling via the B interface calls B.GetStr(), whereas calling via the A interface calls A.GetStr().
Now let's try and write a test for a class that uses interface B:
public class UseB {
B _b;
public UseB(B b) { _b = b; }
public string GetStringFromA() { return ((A) _b).GetStr(); }
}
[Test]
public void TestUseB()
{
var b = MockRepository.GenerateMock<B>();
var sut = new UseB(b);
sut.GetStringFromA();
b.AssertWasNotCalled(x => x.GetStr()); //FAILS
}
Here we make sure UseB.GetStringFromA() calls A.GetStr(), and our test tries to assert that B.GetStr() was not called. This fails, because it seems Rhino Mocks is not differentiating between A.GetStr() and B.GetStr(). You can change the test to assert both A.GetStr() and B.GetStr() were called and the test passes, even though only one of the methods was called. So the following test passes:
[Test]
public void TestUseB() {
var b = MockRepository.GenerateMock<B>();
var sut = new UseB(b);
sut.GetStringFromA();
b.AssertWasCalled(x => x.GetStr());
((A)b).AssertWasCalled(x => x.GetStr());
b.AssertWasCalled(x => ((A)x).GetStr());
b.AssertWasCalled(x => ((B)x).GetStr());
}
I know it's the edge of an edge case, but thought I'd check and see if it were by design or a bug.