在我的单元测试中,如何验证模拟对象引发的事件。
我有一个视图(UI) - > ViewModel - > DataProvider - > ServiceProxy。 ServiceProxy对serivce操作进行异步调用。异步操作完成时,将调用DataProvider上的方法(回调方法作为方法参数传递)。然后回调方法引发ViewModel正在监听的事件。
对于ViewModel测试,我模拟DataProvider并验证DataProvider引发的事件是否存在处理程序。在测试DataProvider时,我模拟了ServiceProxy,但是如何测试调用该回调方法并引发事件。
我正在使用RhinoMock 3.5和AAA语法
由于
- DataProvider -
public partial class DataProvider
{
public event EventHandler<EntityEventArgs<ProductDefinition>> GetProductDefinitionCompleted;
public void GetProductDefinition()
{
var service = IoC.Resolve<IServiceProxy>();
service.GetProductDefinitionAsync(GetProductDefinitionAsyncCallback);
}
private void GetProductDefinitionAsyncCallback(ProductDefinition productDefinition, ServiceError error)
{
OnGetProductDefinitionCompleted(this, new EntityEventArgs<ProductDefinition>(productDefinition, error));
}
protected void OnGetProductDefinitionCompleted(object sender, EntityEventArgs<ProductDefinition> e)
{
if (GetProductDefinitionCompleted != null)
GetProductDefinitionCompleted(sender, e);
}
}
- ServiceProxy -
public class ServiceProxy : ClientBase<IService>, IServiceProxy
{
public void GetProductDefinitionAsync(Action<ProductDefinition, ServiceError> callback)
{
Channel.BeginGetProductDefinition(EndGetProductDefinition, callback);
}
private void EndGetProductDefinition(IAsyncResult result)
{
Action<ProductDefinition, ServiceError> callback =
result.AsyncState as Action<ProductDefinition, ServiceError>;
ServiceError error;
ProductDefinition results = Channel.EndGetProductDefinition(out error, result);
if (callback != null)
callback(results, error);
}
}
答案 0 :(得分:3)
听起来你要编写两个不同的单元测试:
服务代理单元测试:此测试将确保在完成异步调用后将调用发送到ServiceProxy的回调。
数据提供程序单元测试:此测试将确保在调用某个方法时,会引发一个事件(假设有一些订阅者)。
您正在寻找哪一个帮助?
修改强>
对于第1项,我没有看到你需要任何嘲笑。只需提供一个回调函数,在调用时将某些变量设置为true:
// arrange
IServiceProxy serviceProxy = new ServiceProxy();
bool callbackMade;
// act
serviceProxy.GetDataAsync(() => callbackMade = true);
// assert
Assert.IsTrue(callbackMade);
对于第2项,再次,只需订阅单元测试中的事件并确保调用该事件:
// arrange
DataProvider dp = new DataProvider();
bool eventRaised;
dp.DataReturned += (s,e) => eventRaised = true;
// act
dp.DoSomethingThatShouldRaiseEvent();
// assert
Assert.IsTrue(eventRaised)
我不知道你的事件/回调的签名所以我只是做了一些猜测。
答案 1 :(得分:1)
以下示例设置一个IService
存根,它将简单地调用在调用IService.AsyncOperationWithCallBack(Action callback)
时传递给它的任何回调。
// arrange
var serviceStub = MockRepository.GenerateStub<IService>();
serviceStub.Stub(x => x.AsyncOperationWithCallBack(Arg<Action>.Is.NotNull))
.WhenCalled(
invokation =>
{
var callback = (Action)invokation.Arguments[0];
callback();
});
var dataProvider = new DataProvider(serviceStub);
// act
bool raised = false;
dataProvider.MyEvent += delegate { raised = true; };
dataProvider.DoSomething();
// assert
serviceStub.AssertWasCalled(
x=>x.AsyncOperationWithCallBack(Arg<Action>.Is.NotNull));
Assert.IsTrue(raised);