Asp.net Rhinomock事件订阅
作为Rhinomock和单元测试的新手,我遇到了一个似乎无法解决的问题(无论我读了多少文档) 问题是:我创建了一个公开5个事件的接口(用于ASP.NET和MVP监控控制器模式中的视图……我知道,我应该使用MVC,但这是另一个问题)。无论如何,我想测试一下,当某个事件在视图上触发时,我们将其称为“IsLoaded”,调用我的Presenter中的一个方法,并使用依赖项注入,从依赖项返回一个值并设置为视图。问题从这里开始:当我使用Expect.Call(Dependency.GetInfo()).Return(SomeList)时,调用永远不会执行(没有调用mock.ReplayAll()方法)。嗯,当我调用Replayal方法时,我会得到ExpectationExceptions,因为Presenter对象订阅了视图接口公开的其他事件 因此,为了测试IView.IsLoaded是否已启动,我想验证IView.ListOfSomething是否已更新,以匹配我通过Expect.Call()传入的列表。但是,当我设置期望值时,其他事件订阅(直接从演示者的构造函数中发生)未通过测试的#0期望值。我得到的是,view.Save+=this.SaveNewList抛出RhinoMocks ExpectationViolationException 我的百万美元问题是:我是否有必要(通过[Setup])为我的所有事件设定期望值,或者我是否缺少/不了解单元测试或Rhinomock的工作原理Asp.net Rhinomock事件订阅,asp.net,unit-testing,rhino-mocks,Asp.net,Unit Testing,Rhino Mocks,作为Rhinomock和单元测试的新手,我遇到了一个似乎无法解决的问题(无论我读了多少文档) 问题是:我创建了一个公开5个事件的接口(用于ASP.NET和MVP监控控制器模式中的视图……我知道,我应该使用MVC,但这是另一个问题)。无论如何,我想测试一下,当某个事件在视图上触发时,我们将其称为“IsLoaded”,调用我的Presenter中的一个方法,并使用依赖项注入,从依赖项返回一个值并设置为视图。问题从这里开始:当我使用Expect.Call(Dependency.GetInfo()).R
请记住,我对单元测试非常陌生,因此也不熟悉Rhinomock。如果我似乎不知道我在说什么,请随意指出。我正在进行一个项目,我们也使用了MVP和rhino Mock。我们所做的只是在每个测试中期望所有事件订阅
private void SetupDefaultExpectations()
{
_mockView.Initializing += null; LastCall.IgnoreArguments();
_mockView.SavingChanges += null; LastCall.IgnoreArguments();
}
然后,我们在IMockedObject(来自Rhinomock)上构建了一个扩展方法,以触发单元测试中的事件和取消包装异常,从而可以以标准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");
}
为了消除presenter测试之间的重复,我们将其重构为BasePresenterTest基类,该基类为所有presenter测试设置此基本结构,并向子类公开帮助器方法
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);
}
}
public抽象类BasePresenterTest其中视图:IBaseView
{
受保护的MockRepository\u mock;
受保护的视图{get;private set;}
受保护的抽象无效设置();
受保护的抽象void TearDown();
受保护的抽象无效设置DefaultExpections();
[设置]
公共虚拟void BaseSetUp()
{
_mocks=新的MockRepository();
视图=_mocks.CreateMock();
设置();
}
[撕裂]
公共虚拟void basedeardown()
{
撕裂();
视图=空;
_mocks=null;
}
受保护的虚拟void baseSetupDefaultExpections()
{
//设置所有视图的常规默认期望值
设置默认期望();
}
受保护的虚拟IDisposable记录()
{
IDisposable mocksRecordState=_mocks.Record();
baseSetupDefaultExpections();
返回mocksRecordState;
}
受保护的虚拟IDisposable播放()
{
返回_mocks.Playback();
}
受保护的void RaiseEventView(字符串eventName)
{
(作为IMockedObject查看)。RaiseEvent(事件名称);
}
}
这消除了我们项目中测试中的大量代码
我们仍然使用RhinoMocks的旧版本,但一旦我们升级到更高版本,我将尝试更新此版本。只是一个更新,因为它可能会帮助其他有同样问题的人:我发现了致命缺陷。以我的新手方式,我没有使用mock.DynamicMock创建视图mock,而是使用.CreateMock。我真傻。那些“非已定义”的方法调用导致了异常。