2010-02-19 2 views
5

У меня есть API класса, который имеет полный охват кода и использует DI для измельчения всей логики в основной функции класса (Job.Run), которая выполняет всю работу.NMock2.0 - как заглушить вызов без интерфейса?

Я нашел ошибку в производстве, где мы не сделали некоторые проверки на одном из полей ввода данных.

Итак, я добавил функцию заглушки под названием ValidateFoo() ... Написал единичный тест против этой функции, чтобы ожидать исключения JobFailedException, запустил тест - он потерпел неудачу, очевидно, потому что эта функция была пуста. Я добавил логику проверки, и теперь тест проходит.

Отлично, теперь мы знаем, что валидация работает. Проблема в том, как написать тест, чтобы убедиться, что ValidateFoo() действительно вызван внутри Job.Run()? ValidateFoo() - частный метод класса Job - так что это не интерфейс ...

Есть ли все-таки сделать это с помощью NMock2.0? Я знаю, что TypeMock поддерживает подделки типов без интерфейса. Но изменение mock libs сейчас не вариант. В этот момент, если NMock не сможет его поддерживать, я просто просто добавлю вызов ValidateFoo() к методу Run() и проведу проверку вручную - что, очевидно, я бы предпочел не делать, учитывая, что мой метод Job.Run() 100% покрытие прямо сейчас. Любой совет? Большое спасибо.

EDIT: другой вариант, который я имею в виду, - это просто создать интеграционный тест для моей функции Job.Run (введя в нее истинные реализации составных объектов вместо mocks). Я дам ему плохое входное значение для этого поля, а затем подтвержу, что задание не выполнено. Это работает и охватывает мой тест, но на самом деле это не единичный тест, а вместо этого интеграционный тест, который проверяет один блок функциональности .... hmm ..

EDIT2: Есть ли способ сделать это? У кого-нибудь есть идеи? Может быть, TypeMock - или лучший дизайн?

ответ

5

The current version of NMock2 может издеваться конкретных типов (я не помню точно, какую версию они добавили, но мы используем версию 2.1), используя в основном знакомый синтаксис:

Job job = mockery.NewMock<Job>(MockStyle.Transparent); 
Stub.On(job).Method("ValidateFoo").Will(Return.Value(true)); 

MockStyle.Transparent указывает, что все, что вы не нужно останавливать или ожидать, должно быть обработано основной реализацией - так что вы можете заглушить и установить ожидания для методов на экземпляре, который вы тестируете.

Однако вы можете только заглушить и установить ожидания на общедоступные методы (и свойства), которые также должны быть виртуальными или абстрактными. Поэтому, чтобы не полагаться на интеграционное тестирование, у вас есть два варианта:

  • Сделайте Job.ValidateFoo() общедоступным и виртуальным.
  • Извлечь логику проверки в новый класс и вставить экземпляр в Job.
1

Поскольку все частные вызовы называются общедоступными методами (если не полагаться на выполнение выполнения рефлексии), то эти рядовые исполняются общедоступными методами. Эти частные методы вызывают изменения объекта за пределами простого выполнения кода, такие как установка полей класса или вызов на другие объекты. Я бы нашел способ получить эти «результаты» вызова частного метода. (Или высмеивать вещи, которые не должны выполняться в частных методах.)

Я не вижу тестируемый класс.Еще одна проблема, которая может подтолкнуть вас к доступу к частным методам, заключается в том, что это супер большой класс с лодкой частных функций. Эти классы могут быть разбиты на более мелкие классы, и некоторые из этих рядовых могут превратиться в более простые публики.

Смежные вопросы