Используя Rhino Mocks, как установить свойство параметра для метода Mocked

При использовании нового стиля тестирования Rhino Mocks 3.5 Arrange / Act / Assert (AAA) у меня возникают проблемы с написанием теста.

У меня есть метод, который вызывает метод в классе репозитория. ActivateFoo, где мой объект Foo имеет свойство IsActive. Результат объекта ActivateFoo должен изменить свойство.

Вот пример кода:

[TestMethod]
public void Should_update_foo_to_active_inside_of_repository()
{
  // arrange
  var repo = MockRepository.GenerateMock<IRepository>();
  var foo = new Foo() { ID = 1, IsActive = false };
  var target = new Presenter(repo);
  repo.Expect(x => x.ActivateFoo(foo)).Return(true);

  // act
  target.Activate(foo);

  // assert
  Assert.IsTrue(foo.IsActive);
  repo.VerifyAllExpectations();  
}

Я предполагаю, что ключевой фрагмент кода будет между «ActivateFoo (foo))». и «Возврат (истина);».

Один момент, чтобы прояснить, как цепочки методов работают за кулисами. Если в строке, которую я ожидаю, написан код, имеет ли значение, будет ли он после Return () или до него? (если, конечно, решение не использует перегрузку MethodOptions Expect или что-то еще).

Заранее благодарю за любую помощь.


person Andre    schedule 11.03.2009    source источник
comment
Пожалуйста, поясните структуру и соотношение ваших классов. Связь между Foo и Presenter не совсем ясна из вашего примера. Также разверните ActivateFoo (foo) и Activate (foo) в презентаторе.   -  person abhilash    schedule 11.03.2009


Ответы (4)


Возможно, вы захотите попробовать что-то подобное, используя обработчик Do. Я честно считаю, что ActivateFoo должен быть недействительным возвращаемым типом. Но вот код для ActivateFoo с возвращаемым типом bool.

    [TestMethod]
    public void Should_update_foo_to_active_inside_of_repository()
    {
        // arrange
        var repo = MockRepository.GenerateMock<IRepository>();
        var foo = new Foo() { ID = 1, IsActive = false };
        var target = new Presenter(repo);
        repo.Expect(x => x.ActivateFoo(foo)).
            Do(new ActivateFooDelegate(ActivateFooDelegateInstance));
        // act
        target.Activate(foo);

        // assert
        Assert.IsTrue(foo.IsActive);
        repo.VerifyAllExpectations();
    }

    private delegate bool ActivateFooDelegate(Foo f);

    public bool ActivateFooDelegateInstance(Foo f)
    {
        f.IsActive = true;
        return f.IsActive;
    }
person abhilash    schedule 11.03.2009

Благодаря А.Б. Колану это полученный код, который я использовал и работал.

[TestMethod]
public void Should_update_foo_to_active_inside_of_repository()
{
    // arrange
    var repo = MockRepository.GenerateMock<IRepository>();
    var foo = new Foo() { ID = 1, IsActive = false };
    var target = new Presenter(repo);
    repo.Expect(x => x.ActivateFoo(foo)).
        Do(new Func<Foo, bool>(
            delegate(Foo f) { f.IsActive = true; return true; }
        ));

    // act
    target.Activate(foo);

    // assert
    Assert.IsTrue(foo.IsActive);
    repo.VerifyAllExpectations();
}

Мне не нравится иметь дополнительные методы функций для одноразового использования теста, по возможности предпочитаю встроенный делегат.

Чтобы решить вопрос, должен ли я этим заниматься или нет, что касается дизайна. Поскольку имена есть, это не точный код, а внутри метода target.Activate (). Код в Activate () выполняет некоторую проверку и, при необходимости, выполняет ActivateFoo () в репозитории, а затем проверяет результат этой операции и выполняет другие действия.

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

Спасибо

person Andre    schedule 11.03.2009

Я еще не использовал эту версию RhinoMocks, но в старых версиях вам пришлось бы использовать .Do (соответствующий делегат) для установки флага и возврата значения (вместо .Return).

Пожалуйста, дайте мне знать, работает ли он, если нет, я могу с ним поиграться.

person Grzenio    schedule 11.03.2009

Судя по всему, ActivateFoo должен быть недействительным методом. И поскольку вы издеваетесь над ним, вам не следует проверять, что он что-то меняет на вашем объекте.

Вы могли бы убедиться, что свойство IsActive изменено, когда вы тестировали метод ActivateFoo репозитория, а не когда вы тестируете метод Activate на презентаторе.

person Bryan Rowe    schedule 11.03.2009