如何使用内部构造函数模拟事件

时间:2011-04-05 16:34:39

标签: c# events testing moq exchangewebservices

我有一项服务负责订阅EWS以获取新邮件通知。我已经为服务创建了一个接口,以便模拟它并测试一个虚拟实现。但是,每当我试图手动告诉我的事件应该做什么时,我就会碰壁。

这是我的具体实施。

public interface IExchangeService
{
    void Subscribe();
}

public class ExchangeServiceSubscriber : IExchangeService
{
    private readonly ExchangeService _exchangeService;
    private readonly IConsumer<IEmail> _consumer;

    public ExchangeServiceSubscriber(
        ExchangeService exchangeService, 
        IConsumer<IEmail> consumer)
    {
        _exchangeService = exchangeService;
        _consumer = consumer;
    }

    public void Subscribe()
    {
        // code to subscribe

        streamingConnection.OnNotificationEvent += OnEvent;

        streamingConnection.Open();
    }

    public void OnEvent(object sender, NotificationEventArgs args)
    {
        foreach (NotificationEvent triggeredEvent in args.Events)
        {
            if (triggeredEvent is ItemEvent)
            {
                var propertySet = new PropertySet(ItemSchema.UniqueBody, ItemSchema.Attachments)
                {
                    RequestedBodyType = BodyType.Text
                };
                EmailMessage email = EmailMessage.Bind(args.Subscription.Service,
                                                       ((ItemEvent)triggeredEvent).ItemId, propertySet);

                _consumer.Consume(new ExchangeEmail { Body = email.UniqueBody });
            }
        }
    }
}

不幸的是,EWS中的几乎所有课程都是密封的,或者有一个内部构造函数,这似乎限制了我解耦它们的方式。我试图设置NotificationEventArgs的期望(例如),但它使用内部构造函数。

以下是我一直在努力的一些想法。您可以阅读有关模拟事件here的信息。

mock.Setup(x => x.OnEvent(new object(), new NotificationEventArgs())); 问题是NotificationEventArgs使用内部构造函数。

我可以看到这个使用某种包装器,但我不确定它会是什么样子。其中一个重大问题是EWS的制作方式几乎可以防止任何人手动注入依赖关系。我基本上试图测试每当事件OnEvent触发电子邮件实际消耗的时候。此外,虽然我想测试这个功能,但我不确定它是否值得在每一步都与EWS作斗争。

1 个答案:

答案 0 :(得分:3)

让我们先看看你做不到的事情:

  • 您不能将NotificationEventArgs作为子类,因为ctor是内部的。
  • 由于同样的原因,您无法直接创建实例。

所以基本上,你不能使用“普通方式”创建这个类的实例。我假设您已经检查了工厂方法或类?

这给我们留下了一个选项:使用反射实例化类,例如在Activator.CreateInstance方法的帮助下:Unit testing exception handling for third party exceptions with internal constructors,如下所示:

mock.Setup(x => x.OnEvent(new object(), 
           Activator.CreateInstance(typeof(NotificationEventArgs),
                               BindingFlags.NonPublic | BindingFlags.Instance,
                               null,
                               null,
                               null))
           );