1

It appears that the following code doesn't behave as I would expect:

using FakeItEasy;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        var derived = A.Fake<IDerived>();
        A.CallTo(() => derived.Dependency).Returns(null);

        IBase baseObj = derived;
        Assert.IsNull(baseObj.Dependency); //Fails
    }
}

public interface IDerived : IBase
{
    new IDependency Dependency { get; }
}

public interface IBase
{
    IDependency Dependency { get; }
}

public interface IDependency
{
}

Instead of returning null, fake it easy returns a fake instance of IDependency. Perhaps by design? Anyway, how would I go around this problem and ensure baseObj.Dependency returns what was configured?

johnildergleidisson
  • 2,087
  • 3
  • 30
  • 50
  • Note that this question has been raised again as GitHub issue 533, [Faking interface that contains property with new modifier and casting to base interface will have diverted results](https://github.com/FakeItEasy/FakeItEasy/issues/533). I'd expect most discussion to take place there now. – Blair Conrad Sep 10 '15 at 10:43
  • Okay, my point of posting it on github at the time was more of filing a bug. Although it now seems to me it is a feature request. – johnildergleidisson Sep 10 '15 at 13:51

1 Answers1

4

This is normal behavior. IDerived now has two members. One inherited from IBase and one defined in IDerived.

In your test method, your are using FakeItEasy to set the value of the one in IDerived.

The member from IBase was not set. So it get the default value that FakeItEasy gives it which is a mocked IDependency.

If you want to set it, use the following code:

IDerived derived = A.Fake<IDerived>();

IBase baseObj = derived;

A.CallTo(() => baseObj.Dependency).Returns(null);

Assert.IsNull(baseObj.Dependency); //No error here

In this code, we are setting the other member of IDerived, which is the dependency defined in the base interface.

Yacoub Massad
  • 27,509
  • 2
  • 36
  • 62
  • I'm a bit split. On one side I'm thinking, "it should mimic [this code](http://pastebin.com/qzRwC5NW)". On the other side, perhaps FakeItEasy should keep its flexibility there. – johnildergleidisson Sep 08 '15 at 13:10
  • In the Derived class in your referenced code, you have an automatic property. The setter of this property **is not part** of any interface. Under the hood, the setter will store the value in some hidden field. However, the getter of this property is actually implementing two interface properties, IBase.Dependency and IDerived.Dependency. So when your consumer code calls any of these property getters, they will be served by the same implementing getter which reads from the hidden field. – Yacoub Massad Sep 08 '15 at 13:33
  • I'm not sure why mentioning it being an automatic property matters as the behaviour is the same on a property with a backing field. The fact of the matter is, for the concrete implementation, the reference is the same regardless of the type it's cast to. If a derived class implements 50 interfaces having a property with the same name, casting to any of them and accessing the property would result on the same vtable entry for the property, right? `FakeItEasy` does not mimic this behaviour as far as I am concerned. And besides not understanding why I think it can lead to some problems. – johnildergleidisson Sep 08 '15 at 14:00
  • That being said I think the workaround you suggested is the only way to go around that. It'll be a nuance, for sure. – johnildergleidisson Sep 08 '15 at 14:02
  • 2
    The fact that the two property getters are mapped to the same vtable entry is a feature of classes, not interfaces. In your FakeItEasy code, your are mocking an interface, not a class. As far as FakeItEasy is concerned, this interface has two totally different property getters. If you make the Derived.Dependency property virtual (the Derived class), and then use FakeItEasy to mock the Derived class, it would behave exactly as you expect. – Yacoub Massad Sep 08 '15 at 14:13
  • I agree. However the only way one has to create an instance of an object implementing an interface is through a concrete class implementation. So that's the expected behaviour I (maybe mistakenly) expect. The fact that `FakeItEasy` does not mimic that behaviour is what creates the problem for me. In the original code being tested in my project have internal interfaces that have setters and public common interfaces that only have getters, so that values are protected. This is proving to be problematic to test with FakeItEasy. I wouldn't know if other mocking frameworks behave similarly. – johnildergleidisson Sep 08 '15 at 14:39
  • I wish I could hear from @Patrik Hägne about this problem – johnildergleidisson Sep 08 '15 at 14:44
  • 1
    Well, perhaps my expectations are wrong as Moq behaves same way as FakeItEasy... I'm marking your answer as correct and will edit my question adding how I solution to my satisfaction. – johnildergleidisson Sep 09 '15 at 15:03