1

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

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

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

我正在使用 RhinoMock 3.5 和 AAA 语法

谢谢

-- 数据提供者 --

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);
    }
}

-- 服务代理 --

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);
    }
}
4

2 回答 2

3

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

  1. Service Proxy 单元测试:此测试将确保发送到 ServiceProxy 的回调将在异步调用完成后被调用。

  2. 数据提供者单元测试:此测试将确保在调用某个方法时引发事件(假设有一些订阅者)。

你在哪一个上寻求帮助?

编辑:

对于第 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)

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

于 2010-06-04T11:57:19.050 回答
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);
于 2010-06-04T11:55:49.977 回答