Как использовать Machine.Fakes, чтобы конструктор не вызывал локальный метод?

Учитывая конструктор, который должен выдать исключение:

public class MyObject
{
  public MyObject(String name)
  {
    if (String.IsNullOrEmpty(name))
      throw new ArgumentNullException("name");

    this.Initialize();
  }

  protected virtual void Initialize()
  {
    // do stuff
  }
}

Как бы я использовал Machine.Fakes с Rhino (по умолчанию, и я перехожу на Rhino), чтобы смоделировать этот класс и проверить, что:

  1. Выдает ожидаемое исключение
  2. Это не вызывает Initialize()

С Moq я могу смоделировать сам класс MyObject и установить свойство на макете Callbase = true заставить его вести себя как нормальный класс.

Затем я могу проверить, что было сгенерировано исключение, и что метод не был вызван с этим:

// all pseudo code to prove my point of "creating an instance"
//
void when_creating_new_MyObject_with_null_Name_should_throw_Exception()
{
  // arrange
  Mock<MyObject> myObjectToTest = new Mock<MyObject>(String.Empty);
  myObjectToTest.Callbase = true;

  // act
  Assert.Throws<ArgumentNullException>(() => 
    var instance = myObjectToTest.Object;
  );
}

void when_creating_new_MyObject_with_null_Name_should_not_call_Initialize()
{
  // arrange
  Mock<MyObject> myObjectToTest = new Mock<MyObject>(String.Empty);
  myObjectToTest.Callbase = true;

  // act
  try
  {
    // creates an instance
    var instance = myObjectToTest.Object;
  }
  catch {}

  // assert
  myObjectToTest.Verify(x => x.Initialize(), Times.Never());
}

Но у меня возникают проблемы с выяснением, как использовать MSpec с Fakes для макета этого:

[Subject(typeof(MyObject), "when instantiating a new instance")
class with_null_Name
{
  static MyObject myObjectToTest;
  static Exception expectedException;

  Establish context =()=>
    myObjectToTest = An<MyObject>(String.Empty);

  Because of;  // I don't think there is anything to act on here?

  It should_throw_Exception;
    // how to capture exception with An<T>()?

  It should_not_call_Initialize = () =>
    myObjectToTest.WasNotToldTo(x => x.Initialize());

}

Я знаю и использую Catch.Exception(...) обычно в моем Because of действует. Но этот вариант использования, похоже, не работает с этим.

Любые указатели будут оценены.

Спасибо!

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

2 ответа

Решение

Лично я не привык использовать фальшивые фреймворки для насмешек в тестируемом модуле. Я использую mocks, чтобы сломать внешние зависимости, используя внедрение зависимости. Я ни в коем случае не эксперт в этом, но мое интуитивное чувство - то, что это слишком мелкая деталь, чтобы проверить.

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

Эти предложения кажутся мне вонючими. В конце концов, вы знаете, если вы сгенерировали исключение, что Initialize не был вызван. Я думаю, я понимаю, что вы пытаетесь убедиться, что ошибка не появится в будущем редактировании, но вы на самом деле тестируете здесь разработчика? Лично я бы подумал, что достаточно убедиться, что при выдаче неверных данных выдается исключение. Мне интересно услышать любые разные мнения, хотя.

Для меня нет смысла тестировать издеваться sut, фиктивное поведение определяется вами в тестовом методе. Вы должны проверить реальный объект.
В этом случае вы должны проверять, что исключение выдается только при предоставлении неверных данных.
Я думаю, вы знаете, как это сделать, но в любом случае вот код:

[Subject(typeof (MyObject), "when instantiating a new instance")]
internal class with_null_Name
{
    static MyObject myObjectToTest;
    static Exception expectedException;

    Because of = () => expectedException = Catch.Exception(
                    () => myObjectToTest = new MyObject(String.Empty));

    It should_fail = () => expectedException.ShouldNotBeNull();
}
Другие вопросы по тегам