English 中文(简体)
RhinoMocks事件订阅
原标题:
  • 时间:2008-11-26 16:46:55
  •  标签:

作为一个对RhinoMocks和单元测试不熟悉的新手,我遇到了一个问题,无论我阅读多少文档,都无法找到解决方法。

问题在于:我创建了一个接口,暴露了5个事件(用于ASP.NET中的视图和MVP监控控制器模式...我知道,我应该使用MVC,但那是另一个问题)。无论如何,我想测试当视图上触发某个事件(我们将其称为“IsLoaded”)时,我的Presenter内部调用一个方法,并使用依赖注入,从依赖项获取值并将其设置到视图中。问题开始于这里:当我使用Expect.Call(Dependency.GetInfo())。Return(SomeList)时,调用从未执行过(未调用mock.ReplayAll()方法)。好吧,当我调用ReplayAll方法时,由于Presenter对象对View接口暴露的其他事件的订阅,我会得到ExpectationExceptions。

因此,为了测试IView.IsLoaded是否已触发,我希望验证IView.ListOfSomething是否已更新以匹配通过Expect.Call()传递的列表。然而,当我设置期望值时,其他事件订阅(这些订阅直接从Presenter的构造函数中发生)会失败测试的#0期望。我得到的是,view.Save += this.SaveNewList会引发RhinoMocks ExpectationViolationException。

我的百萬美元問題是: 我是否需要為我所有的事件設置期望值(通過[設置]),還是我對單元測試或RhinoMocks的工作方式缺乏理解?

请记住,我对单元测试和RhinoMocks非常陌生。如果我说话显得不懂,请随时指出。

最佳回答

我正在进行一个项目,其中我们使用了 MVP 和 Rhino Mocks。我们所做的就是在每个测试中简单地期望所有事件订阅。

    private void SetupDefaultExpectations()
    {
        _mockView.Initializing += null; LastCall.IgnoreArguments();
        _mockView.SavingChanges += null; LastCall.IgnoreArguments();
    }

然后我们在IMockedObject上(来自RhinoMocks)构建了一个扩展方法,在单元测试中触发事件并解开异常,以便可以按照标准的NUnit方式进行期望。

static class IMockedObjectExtension
{
    public static void RaiseEvent(this IMockedObject mockView, string eventName, EventArgs args)
    {
        EventRaiser eventraiser = new EventRaiser(mockView, eventName);

        try
        {
            eventraiser.Raise(mockView, args);
        }
        catch (TargetInvocationException ex)
        {
            throw ex.InnerException;
        }
    }

    public static void RaiseEvent(this IMockedObject mockView, string eventName)
    {
        RaiseEvent(mockView, eventName, EventArgs.Empty);
    }
}

这可以从单元测试中使用,像这样。

using(_mocks.Record())
{
    Expect.Call(dependency.GetInfo()).Return(someList);
}
using(_mocks.Playback())
{
    Presenter presenter = new Presenter(_mockView, dependency);
    (_mockView as IMockedObject).RaiseEvent("SavingChanges");
}

为了消除演示者测试之间的重复,我们对其进行了重构,将其转换为 BasePresenterTest 基类,为所有演示者测试设置了这个基本结构,并向子类公开了辅助方法。

public abstract class BasePresenterTest<VIEW> where VIEW : IBaseView
{
    protected MockRepository _mocks;
    protected VIEW View { get; private set; }

    protected abstract void SetUp();
    protected abstract void TearDown();
    protected abstract void SetupDefaultExpectations();

    [SetUp]
    public virtual void BaseSetUp()
    {
        _mocks = new MockRepository();
        View = _mocks.CreateMock<VIEW>();

        SetUp();
    }

    [TearDown]
    public virtual void BaseTearDown()
    {
        TearDown();

        View = null;
        _mocks = null;
    }

    protected virtual void BaseSetupDefaultExpectations()
    {
        //Setup default expectations that are general for all views
        SetupDefaultExpectations();
    }

    protected virtual IDisposable Record()
    {
        IDisposable mocksRecordState = _mocks.Record();

        BaseSetupDefaultExpectations();

        return mocksRecordState;
    }

    protected virtual IDisposable Playback()
    {
        return _mocks.Playback();
    }

    protected void RaiseEventOnView(string eventName)
    {
        (View as IMockedObject).RaiseEvent(eventName);
    }       
}

这能从我们项目的测试中删除许多代码。

我们仍在使用旧版本的RhinoMocks,但一旦我们转向较新版本,我将尝试更新它。

问题回答

暂无回答




相关问题
热门标签