Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moq - mock.Raise should raise event in tested unit without having a Setup

Tags:

c#

tdd

mvp

events

moq

I have a presenter class, that attaches an event of the injected view. Now I would like to test the presenter reacting correctly to the event.

This is the view interface IView:

public interface IView  {     event EventHandler MyEvent;     void UpdateView(string test); } 

This is the view implementing IView:

public partial class MyView : IView {     public event EventHandler MyEvent;      public MyView()     {         this.combo.SelectedIndexChanged += this.OnSelectedIndexChanged;     }      public void UpdateView(string test)     {         this.textBox.Text = test;     }      private OnSelectedIndexChanged(Object sender, EventArgs e)     {         if (this.MyEvent != null)         {             this.MyEvent(sender, e);         }     } } 

This is the presenter under test:

public class MyPresenter {     private IView _view;     public MyPresenter(IView view)     {         this._view = view;         this._view.MyEvent += this.OnMyEvent;     }      private void OnMyEvent(Object sender, EventArgs e)     {         this._view.UpdateView();     } } 

This is the test fixture testing MyPresenter:

[TestClass] public class MyPresenterFixture() {     private MyPresenter testee;     private Mock<IView> mockView;      [TestMethod]     public void ShouldReactOnMyEvent()     {         // arrange         this.mockView = new Mock<IView>(MockBehavior.Strict);         this.testee = new MyPresenter(this.mockView.Object);          // act         this.mockView.Raise(mock => mock.MyEvent += null); // this does not fire          // assert and verify         this.mockView.Verify(mock => mock.UpdateView(It.IsAny<string>());     } } 

I am using Moq 4. Is it possible to do what I want?

like image 791
Yannik Avatar asked May 16 '11 11:05

Yannik


2 Answers

Don't you need to pass the argument? Your event signature is EventHandler, which is
(object sender, EventArgs e).

this.mockView.Raise(mock => mock.MyEvent += null, new EventArgs()); 

I've never used the overload you've specified here... it doesn't seem correct, though.

like image 113
Anderson Imes Avatar answered Sep 17 '22 12:09

Anderson Imes


You've declared UpdateView() as accepting a string, but your presenter invocation does not have a string argument (or default):

Invocation:

private void OnMyEvent(Object sender, EventArgs e) {     this._view.UpdateView(); } 

Declaration:

public void UpdateView(string test) {     this.textBox.Text = test; } 

Verification:

mockView.Verify(mock => mock.UpdateView(It.IsAny<string>()); 

FWIW, I think the event in your view is a bit cumbersome, a simple change would be to:

public interface IView {     void UpdateText(string test); }  public class MyPresenter {     private readonly IView _view;     public MyPresenter(IView view)     {         _view = view;     }      private void SelectItem(string item)     {         _view.UpdateText(item);     } }  public partial class MyView : IView {     private readonly MyPresenter _presenter;      public MyView()     {         _presenter = new MyPresenter(this);         combo.SelectedIndexChanged += OnSelectedIndexChanged;     }      public void UpdateText(string test)     {         textBox.Text = test;     }      private OnSelectedIndexChanged(Object sender, EventArgs e)     {         _presenter.SelectItem(combo.SelectedItem);     } } 

Then you could just verify the interaction with the view without having an additional event to deal with:

    presenter.SelectItem("Burrito!");      mockView.Verify(mock => mock.UpdateView("Burrito!"); 
like image 41
Ritch Melton Avatar answered Sep 20 '22 12:09

Ritch Melton