作为RhinoMocks和Unit Testing的新手,我遇到了一个似乎无法找到解决方案的问题(无论我阅读了多少文档)。
问题是:我创建了一个公开5个事件的接口(用于ASP.NET中的视图和MVP监控模式......我知道,我应该使用MVC,但那是另一个问题)。无论如何,我想测试当某个事件在视图上触发时,我们将其称为“IsLoaded”,调用我的Presenter内部的方法,并使用依赖注入从依赖关系返回一个值并设置为风景。这是问题开始的地方:当我使用Expect.Call(Dependency.GetInfo())。返回(SomeList)时,调用永远不会执行(没有调用mock.ReplayAll()方法)。好吧,当我调用ReplayAll方法时,由于Presenter对象对View接口公开的其他事件的订阅,我得到了ExpectationExceptions。
因此,为了测试IView.IsLoaded已经触发,我想验证IView.ListOfSomething已经更新以匹配我通过Expect.Call()传入的列表。但是,当我设置期望时,其他事件订阅(直接出自Presenter的构造函数)未通过测试的#0期望。我得到的是,view.Save + = this.SaveNewList抛出了RhinoMocks ExpectationViolationException。
我的百万美元问题是这样的:我是否有必要为所有事件设定期望(通过[设置]),或者是否有一些我缺少/不理解单元测试或RhinoMocks如何工作的东西?
请记住,我是非常新的单位测试,因此是RhinoMocks。如果看起来我不知道我在说什么,请随时指出。
答案 0 :(得分:2)
我正在开展一个我们使用MVP和犀牛模拟的项目。我们所做的只是期望每次测试中的所有事件订阅。
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,但是一旦我们转移到更高版本,我会尝试更新。