Модульный тест, что метод void для класса выполняется при возникновении события - PullRequest
2 голосов
/ 07 ноября 2010

Предположим, у вас было 2 класса, Слушатель и Говорящий. У Talker есть событие Talking, и когда оно запускается, Listener должен выполнить метод vear HeardTalk, как показано ниже:

public class Talker
{
   public event EventHandler Talking;

   public void Talk()
   {
      if (Talking != null)
      {
         Talking(this, null);
      }
   }
}

public class Listener
{
   public void StartListening(Talker talker)
   {
      talker.Talking += HeardTalk;
   }

   public void HeardTalk(object sender, EventArgs e)
   {
      // do something private here
   }
}

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

Есть ли элегантный способ утверждать, что метод вызывается на SUT, не модифицируя его только для целей тестируемости?

Ответы [ 2 ]

3 голосов
/ 07 ноября 2010

Должно быть не менее некоторого измеримого побочного эффекта от инициируемого события. Возможно, вы регистрируете событие, сохраняете что-то в хранилище данных или изменяете внутреннее состояние вашего класса.

Если вы обращаетесь к каким-либо внешним зависимостям, они должны быть переданы через конструктор / внедрение свойства и смоделированы. В случае изменения внутреннего состояния даже такое действие должно иметь некоторый побочный эффект, который можно наблюдать снаружи. Иначе в чем смысл?

В конце концов, если все, что вы хотите проверить, это то, что метод был вызван, то что вы на самом деле тестируете? Опять же, должна быть причина, по которой вызывается метод, и эта причина должна иметь некоторое влияние, которое можно наблюдать где-то ...

1 голос
/ 07 ноября 2010

Вы можете легко делать такие вещи с помощью коммерческого Typemock Isolator , который позволяет вам выборочно «насмехаться» над отдельными методами над «реальными» объектами.Тест будет выглядеть так:

[Test, Isolated]
public void HeardTalk_GetsCalled()
{
    // --- Arrange ---
    var talker = new Talker();
    var listener = new Listener();
    bool heardTalkWasCalled = false;
    Isolate.WhenCalled(() => listener.HeardTalk(null, null))                     // Selectively 'mock' the call to 'listener.HeardTalk()'
                                     .DoInstead(x => heardTalkWasCalled = true); // on the live object (arguments are ignored by default)

    // --- Act ---
    listener.StartListening(talker);
    talker.Talk();

    // --- Assert ---
    Assert.IsTrue(heardTalkWasCalled);
}

По общему признанию, Typemock Isolator поставляется с некоторыми лицензионными затратами.Но если вы серьезно относитесь к тестированию и вам нужно протестировать множество подобных вещей, как указано выше, это стоит каждого пенни из-за его прочности и гибкости.

Примечания:

  • Вы можете сделать то же самое с бесплатной платформой MS Moles (для Visual Studio 2010), которая является подходящей альтернативой Typemock, если такие тесты приходится делать только изредка,Как правило, для этого требуется несколько больше работы / кода, что усложняет тестирование и требует более высокой производительности, особенно во время компиляции, но достаточно для небольших тестовых наборов.
  • Существует также коммерческая альтернатива от Telerik, называемая JustMock .Поскольку он совершенно новый, я ничего не могу сказать об этом, кроме того, что он существует ...

HTH!Thomas

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...