FakeItEasy: Default behavior of read/write properties should not override explicit getter or setter configuration

(Spawned from a discussion on the chat)

I recently noticed a surprising behavior for faked read/write properties. As documented, setting the value of an unconfigured property configures it to return the assigned value. But when you do that, it also overrides any configuration made on the setter. The same is true when you read an unconfigured property.

Neither of these code snippets throw an exception:

    var foo = A.Fake<IFoo>();
    A.CallToSet(() => foo.Bar).To(() => A<int>.That.Not.IsEqualTo(42)).Throws(new Exception("wrong answer"));
    foo.Bar = 42; // previously configured behavior is overridden here
    foo.Bar.Dump();
    foo.Bar = 123; // should throw here, but doesn't
    foo.Bar.Dump();
    var foo = A.Fake<IFoo>();
    A.CallToSet(() => foo.Bar).To(() => A<int>.That.Not.IsEqualTo(42)).Throws(new Exception("wrong answer"));
    foo.Bar.Dump(); // previously configured behavior is overridden here
    foo.Bar = 123; // should throw here, but doesn't
    foo.Bar.Dump();

We should probably consider changing this behavior, as it is counter-intuitive.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 43 (42 by maintainers)

Most upvoted comments

Hi @DanielRose,

You can make it a bit simpler:

A.CallToSet(() => foo.Bar).Invokes((int bar) =>
{
    A.CallTo(() => foo.Bar).Returns(bar);
    foo.BarChanged += Raise.With(foo, EventsArgs.Empty);
});

It’s true that the documentation could be more explicit. The fact that the “natural” property behavior no longer applies when the property is explicitly configured is mentioned here, but maybe we could elaborate on the implications.