C# 验证模拟对象是否引发了事件

C# 验证模拟对象是否引发了事件,c#,rhino-mocks,rhino-mocks-3.5,C#,Rhino Mocks,Rhino Mocks 3.5,在单元测试中,如何验证模拟对象是否引发了事件 我有一个视图(UI)-->ViewModel-->数据提供程序-->ServiceProxy。ServiceProxy对serivce操作进行异步调用。异步操作完成后,将调用DataProvider上的方法(回调方法作为方法参数传递)。然后回调方法引发ViewModel正在侦听的事件 对于ViewModel测试,我模拟DataProvider并验证DataProvider引发的事件是否存在处理程序。在测试DataProvider时,我模拟Servic

在单元测试中,如何验证模拟对象是否引发了事件

我有一个视图(UI)-->ViewModel-->数据提供程序-->ServiceProxy。ServiceProxy对serivce操作进行异步调用。异步操作完成后,将调用DataProvider上的方法(回调方法作为方法参数传递)。然后回调方法引发ViewModel正在侦听的事件

对于ViewModel测试,我模拟DataProvider并验证DataProvider引发的事件是否存在处理程序。在测试DataProvider时,我模拟ServiceProxy,但如何测试调用回调方法并引发事件

我正在使用RhinoMock 3.5和AAA语法

谢谢

--数据提供者--

公共部分类数据提供程序
{
公共事件事件处理程序GetProductDefinition已完成;
public void GetProductDefinition()
{
var service=IoC.Resolve();
GetProductDefinitionAsync(GetProductDefinitionAsyncCallback);
}
私有void GetProductDefinitionAsyncCallback(ProductDefinition ProductDefinition,ServiceError错误)
{
OnGetProductDefinition已完成(此,新EntityEventArgs(productDefinition,error));
}
已完成受保护的void OnGetProductDefinition(对象发送方,EntityEventArgs e)
{
如果(GetProductDefinitionCompleted!=null)
GetProductDefinition已完成(发件人,e);
}
}
--服务代理--

公共类ServiceProxy:ClientBase,IServiceProxy
{
public void GetProductDefinitionAsync(操作回调)
{
Channel.BeginGetProductDefinition(EndGetProductDefinition,回调);
}
私有void EndGetProductDefinition(IAsyncResult结果)
{
动作回调=
result.AsyncState作为操作;
服务错误;
ProductDefinition结果=Channel.EndGetProductDefinition(输出错误,结果);
if(回调!=null)
回调(结果、错误);
}
}

下面的示例设置了一个
iSeries设备
存根,当调用
iSeries设备.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);
//排列
var serviceStub=MockRepository.GenerateStub();
serviceStub.Stub(x=>x.AsyncOperationWithCallBack(Arg.Is.NotNull))
.什么时候(
调用=>
{
var callback=(Action)invokation.Arguments[0];
回调();
});
var dataProvider=新的数据提供程序(serviceStub);
//表演
bool=false;
dataProvider.MyEvent+=委托{raised=true;};
dataProvider.DoSomething();
//断言
serviceStub.AssertWasCalled(
x=>x.AsyncOperationWithCallBack(Arg.Is.NotNull));
断言。IsTrue(升起);

下面的示例设置了一个
iSeries设备
存根,当调用
iSeries设备.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);
//排列
var serviceStub=MockRepository.GenerateStub();
serviceStub.Stub(x=>x.AsyncOperationWithCallBack(Arg.Is.NotNull))
.什么时候(
调用=>
{
var callback=(Action)invokation.Arguments[0];
回调();
});
var dataProvider=新的数据提供程序(serviceStub);
//表演
bool=false;
dataProvider.MyEvent+=委托{raised=true;};
dataProvider.DoSomething();
//断言
serviceStub.AssertWasCalled(
x=>x.AsyncOperationWithCallBack(Arg.Is.NotNull));
断言。IsTrue(升起);

听起来您需要编写两个不同的单元测试:

  • 服务代理单元测试:此测试将确保在异步调用完成时调用发送到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)
    

    我不知道您的事件/回调的签名,所以我只是做了一些猜测。

    听起来您有两个不同的单元测试要编写:

  • 服务代理单元测试:此测试将确保在异步调用完成时调用发送到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)
    

    我不知道您的事件/回调的签名,所以我只是做了一些猜测。

    很抱歉耽搁了。对于第二个测试,问题是doSomethingthastshouldriaseevent不是数据提供程序上的公共方法。它是传递给ServiceProxy的回调方法。如果您提供了DataProvider上的方法以及它们如何与ServiceProxy类交互,thanksIt可能会有所帮助。我认为将其分为两个不同的单元测试是一个良好的开端。然后,您可以让fancier将它们耦合到集成测试中(尽管单独的单元测试将有助于确保各个组件的行为符合设计/预期)。您好,感谢您的回复。我在最初的文章中介绍了数据提供者和服务代理的实现。DoSomethingthastShouldRiaseEvent(GetProductDefinitionAsyncCallback)不是公共方法。ThanksI无法创建ServiceProxy的实例(它是一个WCF服务),因为它