Moq - mock.Raise应该在被测试的单元中引发事件,而无需设置。

46
我有一个 presenter 类,它附加了一个注入视图的事件。现在我想测试 presenter 对事件的正确反应。 这是视图界面 IView:
public interface IView 
{
    event EventHandler MyEvent;
    void UpdateView(string test);
}

这是实现了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);
        }
    }
}

这是待测试的演示者:

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

这是测试夹具,用于测试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>());
    }
}

我正在使用Moq 4。 我想知道是否有可能做到我想要的。

2个回答

93

你不需要传递参数吗?因为你的事件签名是 EventHandler,它是
(object sender, EventArgs e)

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

我从未使用过你在此处指定的重载... 它似乎不正确,但我不确定。


4
+1. 或者传入 EventArgs.Empty。在调用 Mock.Raise 时,需要将除发送方以外的任何参数作为参数传递。链接:http://madcoderspeak.blogspot.com/2010/01/meet-frameworks-rhino-v-moq-v-jmock.html#scen8 http://code.google.com/p/moq/wiki/QuickStart - Gishu
1
为什么我们要使用 mock.MyEvent += null ?? 请解释一下,因为我是新手。 - Bhoopathi Reddy
1
@BhoopathiReddy:事件只能出现在+=或-=的左侧。请参见CS0079 - RuudSieb

3
您已将UpdateView()声明为接受一个字符串,但是您的Presenter调用没有字符串参数(或默认值):

调用:

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

声明:

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

验证:

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

就我个人而言,我认为你所提到的事件有些繁琐,一个简单的改变是:

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

那么你只需要验证与视图的交互,而无需处理额外的事件:

    presenter.SelectItem("Burrito!");

    mockView.Verify(mock => mock.UpdateView("Burrito!");

嗨,Ritch,感谢你的反馈。我注意到在presenters方法private void OnMyEvent(Object sender,EventArgs e){ this._view.UpdateView(); }中,UpdateView的输入缺失。不幸的是,你的方法对我们没有用,因为我们实现了纯被动视图,而视图永远不会知道它的呈现者。干杯 - Yannik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接