0

In the example below FakeItEasy return 0 even though the IThing member GetValue() has not been defined. My question is; why is a value of 0 returned from an undefined member call and not an exception thrown; is there some general mocking/faking/stubbing framework software pattern that dictates that throwing exceptions for calling undefined members is a no-no?

public interface IThing
{
    int GetValue();
}

public class Thing: IThing
{
    public int GetValue()
    {
        return 1000;
    }
}

    [TestMethod]
    public void Test1()
    {
        var thing= A.Fake<IThing>();
        // A.CallTo(() => thing.GetValue()).Returns(1);
        var val = thing.GetValue(); // Not defined but returns 0 rather than throwing an exeption
        Assert.AreEqual(1, val);
    }
  • You're defining your fake in the line `var thing= A.Fake();` This creates a fake IThing object (a fake object which is an IThing, not a Thing object). 0 will just be the default value of an int (as you've not specified for it to return anything else). I'm not sure about exception behaviour in general but it won't throw in this case as everything is valid. – Tone Apr 09 '16 at 02:48
  • @Tone This is not what I'm asking. A runtime exception is the expected behaviour when calling undefined member in the .NET Runtime as it is Strongly-Typed, and my question is why Mocking frameworks have a looser semantic. –  Apr 09 '16 at 09:27

1 Answers1

2

This is largely an opinion-based question, and will probably be closed. However, here's some information. First, some frameworks are strict by default, and some allow looser semantics. FakeItEasy tends toward the latter. Reasons given for this choice are often that such a style supports less brittle tests - because the user doesn't have to define every interaction with a fake object (or mock, or whatever you want to call it), when "unimportant" things change, your tests don't break "for no reason".

Some people like strict semantics, and some don't.

Note that if you want the strict behaviour, you can get it in FakeItEasy by using strict fakes

var thing= A.Fake<IThing>(options => options.Strict());

And in FakeItEasy 2.0.0-rc1, you can use implicit creation options to turn this behaviour on globally, by implementing an options builder like this:

class MakeEverythingStrictOptionsBuilder : IFakeOptionsBuilder
{
    public bool CanBuildOptionsForFakeOfType(Type type)
    {
        return true;
    }

    public void BuildOptions(Type typeOfFake, IFakeOptions options)
    {
        options.Strict();
    }

    public Priority Priority
    {
        get { return Priority.Default; }
    }
}
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
Blair Conrad
  • 233,004
  • 25
  • 132
  • 111