1

I would like to stub a property on a mock object, and have an event fired whenever my test calls the setter for that property. Something like the following. Given:

public interface ISomething
{
    event Action FooChanged;
    int Foo { get; set; }
}

I would like to have a test like this (and of course this does not compile):

[Test]
public void HandleChangeInDependencyObject()
{
    var mock = new Mock<ISomething>();
    mock.SetupProperty(m => m.Foo).Raises(m => m.FooChanged += null);
    mock.Object.Foo = 5; // raises the FooChanged event on ISomething
    ...
}

Is this possible with Moq? All I could find was a post from 2009 on a Google Groups forum discussing it.

Cellcon
  • 1,245
  • 2
  • 11
  • 27
Brian Stewart
  • 9,157
  • 11
  • 54
  • 66

1 Answers1

0

This worked for me:

var mock = new Mock<ISomething>();
var raised = false;
// Setup the property to only raise an event it '5' is passed.  Instead of '5' you can
// specify It.IsAny<int>() to fire on any value, or It.Is<int>(expr) to fire on some
// range of values.
mock.SetupSet(m => m.Foo = 5).Raises(s => s.FooChanged += null);
mock.Object.FooChanged += () =>
    {
        Console.WriteLine("FooChanged fired");
        raised = true;
    };

Console.WriteLine("Setting Foo to 5...");
mock.Object.Foo = 5; // raises the FooChanged event on ISomething
Assert.That(raised, Is.True);

// Make sure the event is not raised if the set value is not in range
Console.WriteLine("Setting Foo to 6...");
raised = false;
mock.Object.Foo = 6; // No setup for '6'
Assert.That(raised, Is.False);

It's kind of counter-intuitive, but because event delegates cannot be invoked outside of the class that defines them the only way to reference them is to provide a valid but otherwise meaningless from which MoQ can extract the event reference, such as s.FooChanged += null.

(Credit to this StackOverflow post for providing that critical piece of information.)

Community
  • 1
  • 1
Jesse Sweetland
  • 1,594
  • 11
  • 10