Как макетировать события с помощью внутренних конструкторов - PullRequest
2 голосов
/ 05 апреля 2011

У меня есть служба, отвечающая за подписку на 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 (например), но он использует внутренний конструктор.

Вот некоторые идеи, с которыми я возился. Вы можете прочитать о насмешливых событиях здесь .

mock.Setup(x => x.OnEvent(new object(), new NotificationEventArgs())); Проблема в том, что NotificationEventArgs использует внутренний конструктор.

Я мог видеть, как это работает с какой-то оберткой, но я не совсем уверен, как это будет выглядеть. Одна из больших проблем заключается в том, что EWS не позволяет никому вводить зависимости вручную. По сути, я пытаюсь проверить, что всякий раз, когда срабатывает событие OnEvent, электронное письмо действительно будет использовано. Кроме того, хотя я хотел бы протестировать эту функциональность, я не уверен, что стоит бороться с EWS на каждом этапе.

1 Ответ

3 голосов
/ 05 апреля 2011

Давайте сначала посмотрим, что вы не можете сделать:

  • Вы не можете подкласс NotificationEventArgs, потому что ctor является внутренним.
  • Вы не можете создать экземпляр напрямую по той же причине.

Так что, по сути, вы не можете создать экземпляр этого класса, используя "обычный путь". Я полагаю, вы уже проверили фабричный метод или класс?

Это оставляет нам только один вариант: создать экземпляр класса с помощью отражения, например с помощью метода Activator.CreateInstance: Обработка исключений модульного тестирования для исключений сторонних разработчиков с внутренними конструкторами , например:

mock.Setup(x => x.OnEvent(new object(), 
           Activator.CreateInstance(typeof(NotificationEventArgs),
                               BindingFlags.NonPublic | BindingFlags.Instance,
                               null,
                               null,
                               null))
           );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...