Raising events from a mock/stub using Rhino Mocks

haagel picture haagel · Nov 8, 2010 · Viewed 10.9k times · Source

How can I raise an event from a mock/stub using Rhino Mocks?

I've found some answers to this question on the web, but they all seem to use the Record/Replay-syntax, but I'm using the Arrange/Act/Assert syntax.

Any suggestions?

A little example...

Let's say I'm using the MVVM pattern and have this model class:

public class MyModel
{
    private int _myValue;

    public event EventHandler ValueChanged;

    public void SetValue(int newValue)
    {
        _myValue = newValue;
        if (ValueChanged != null)
        {
            ValueChanged(this, null);
        }
    }
}

As you can see the class has an integer value and a method that sets it. When the value is set, a ValueChanged event is raised.

This model class is used by a viewmodel:

public class MyViewModel
{
    private MyModel _myModel;

    public MyViewModel(MyModel myModel)
    {
        _myModel = myModel;
        _myModel.ValueChanged += ValueChangedHandler;
    }

    private void ValueChangedHandler(object sender, EventArgs e)
    {
        MyString = "Value has changed";
    }

    public string MyString { get; set; }
}

This viewmodel listen to the ValueChanged event on the model and updates when it is raised.

Now I want to test that the viewmodel is updated when the model raises the event.

[TestMethod]
public void MyViewModel_ModelRaisesValueChangedEvent_MyStringIsUpdated()
{
    //Arrange.
    var modelStub = MockRepository.GenerateStub<MyModel>();
    MyViewModel viewModel = new MyViewModel(modelStub);

    //Act
    -HERE I WANT TO RAISE THE VALUE CHANGED EVENT FROM modelStub.

    //Assert.
    Assert.AreEqual("Value has changed", viewModel.MyString);
}

Note that this is just an example and not my actual code (which is more complex). I hope you can disregard any typos and other small mistakes.

Answer

Wim Coenen picture Wim Coenen · Nov 8, 2010
[TestMethod]
public void MyViewModel_ModelRaisesValueChangedEvent_MyStringIsUpdated()
{
    //Arrange.
    var modelStub = MockRepository.GenerateStub<IModel>();
    MyViewModel viewModel = new MyViewModel(modelStub);

    //Act
    modelStub.Raise(
       x => x.ValueChanged += null,
       modelStub, // sender
       EventArgs.Empty);

    //Assert.
    Assert.AreEqual("Value has changed", viewModel.MyString);
}

Edit: The error you are encountering can probably be solved by changing the stub type to an interface IModel (that's how my own tests work). I have changed it in example above, but you will also have to change the MyViewModel constructor declaration to take the interface type.

Adding the virtual keyword to the event declaration may also work.