是否可以在Moq中存根属性并在设置操作中引发事件?

时间:2014-02-19 17:37:28

标签: unit-testing events properties moq

我想在模拟对象上存根一个属性,并且只要我的测试调用该属性的setter就会触发一个事件。像下面这样的东西。给出:

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

我想进行这样的测试(当然这不会编译):

[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
    ...
}

Moq可以实现吗?我可以在Google网上论坛论坛上找到a post from 2009进行讨论。

1 个答案:

答案 0 :(得分:0)

这对我有用:

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);

这有点反直觉,但是因为事件委托不能在定义它们的类之外调用,所以引用它们的唯一方法是提供有效但无意义的MoQ可以从中提取事件引用,例如{ {1}}。

(感谢this StackOverflow post提供关键信息。)