Проверка защищенных абстрактных методов вызывается с помощью Moq - PullRequest
3 голосов
/ 24 декабря 2008

Предположим, у меня есть следующий класс:

public class TestBase
{
  public bool runMethod1 { get; set; }

  public void BaseMethod() 
  {
    if (runMethod1)
      ChildMethod1();
    else 
      ChildMethod2();
  }

  protected abstract void ChildMethod1();
  protected abstract void ChildMethod2();
}

У меня тоже есть класс

public class ChildTest : TestBase
{
  protected override void ChildMethod1()
  {
    //do something
  } 

  protected override void ChildMethod2()
  {
    //do something completely different
  }

}

Я использую Moq, и я хотел бы написать тест, который проверяет, вызывается ли ChildMethod1 (), когда я вызываю BaseMethod (), а runMethod1 имеет значение true. Можно ли создать реализацию TestBase с Moq, вызвать BaseMethod () и убедиться, что ChildMethod был вызван в реализации Moq?

[Test]
public BaseMethod_should_call_correct_child_method()
{
  TestBase testBase;

  //todo: get a mock of TestBase into testBase variable

  testBase.runMethod1 = true;

  testBase.BaseMethod();

  //todo: verify that ChildMethod1() was called

}

Ответы [ 4 ]

5 голосов
/ 03 февраля 2009

Вы также можете установить ожидание / настройку как Verifiable и обойтись без строгой насмешки:

  //expect that ChildMethod1() will be called once. (it's protected)
  testBaseMock.Protected().Expect("ChildMethod1")
    .AtMostOnce()
    .Verifiable();

  ...

  //make sure the method was called
  testBase.Verify();

Редактировать Этот синтаксис не работает в текущих версиях Moq. См. этот вопрос , чтобы узнать, как это сделать, начиная с версии 4.0.10827

.
4 голосов
/ 24 декабря 2008

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

[Test]
public BaseMethod_should_call_correct_child_method()
{
  //strict mocks will make sure all expectations are met
  var testBaseMock = new Mock<TestBase>(MockBehavior.Strict);

  //expect that ChildMethod1() will be called once. (it's protected)
  testBaseMock.Protected().Expect("ChildMethod1")
    .AtMostOnce();

  var testBase = testBaseMock.Object;

  testBase.runMethod1 = true;
  testBase.BaseMethod();

  //make sure the method was called
  testBase.VerifyAll();
}
1 голос
/ 24 декабря 2008

Это что-то вроде хака, но как насчет создания подкласса TestBase, который делает ChildMethod1 и ChildMethod общедоступными, а затем Moqing?

0 голосов
/ 24 декабря 2008

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

"Можно ли создать реализацию TestBase с Moq, вызвать BaseMethod () и убедиться, что ChildMethod был вызван в реализации Moq?"

Это вроде возможно. Но тогда вы будете тестировать фиктивный объект, а не реальный объект.

Два вопроса, которые могут направить вас в правильном направлении:

  1. Возвращает ли класс downndatn значение, отличное от базового класса? Если это так, вы можете проверить это и проигнорировать детали имплиментации (также значительно упрощает рефакторинг).

  2. Вызывает ли класс-потомок разные методы или разные зависимости? Если это так, вы можете проверить зависимости.

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