Как я могу обойти выполнение метода в макете RhinoMocks?

Я использую RhinoMocks для очень простого теста (должен сказать, что я здесь новичок). Я пытался издеваться над своим объектом вот так

var mock = MockRepository.GenerateMock<MyClass>();

создать вспомогательную заглушку:

var stubLinkedObject = MockRepository.GenerateStub<MyClass>();

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

mockAction.AssertWasCalled(a => a.AddLink(stubLinkedObject));

Я ввел правильную зависимость, и метод действительно вызван. Однако проблема в том, что вызывается настоящая реализация в MyClass, что приводит к сбою, потому что некоторая логика просто не может быть выполнена (сбор ссылок недоступен и т. Д.). Как я могу обойти выполнение и просто проверить, вызывается ли метод? Я пробовал что-то вроде

mockAction.Stub(a => a.AddLink(null)).IgnoreArguments().Do(null);

прежде чем я перейду к выполнению, но это, похоже, не работает (у меня есть только некоторые исключения). Любые идеи и, возможно, объяснение, почему макет вообще выполняет логику метода?


person Tomas Vana    schedule 08.02.2010    source источник
comment
Ваш метод AddLink виртуальный?   -  person dh.    schedule 08.02.2010
comment
Нет, наверное, в этом проблема :)   -  person Tomas Vana    schedule 08.02.2010
comment
Я смущен. Обычно должен быть один экземпляр объекта тестируемого класса, который не является имитируемым / заглушенным. У вас, кажется, есть только моки и заглушки. Мокинг и заглушка предназначены только для объектов-соавторов, которыми вы должны управлять во время теста.   -  person Wim Coenen    schedule 08.02.2010
comment
На самом деле тестируемая часть (и класс) отсутствует, и проверка заключается в том, что этот объект в ходе выполнения вызывает метод AddLink.   -  person Tomas Vana    schedule 08.02.2010


Ответы (2)


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

[Test]
public void Test()
{
    var classMock = MockRepository.GenerateMock<MyClass>();
    var linkedMock = MockRepository.GenerateStub<MyClass>();

    classMock.Expect(c => c.MyMethod(linkedMock));

    classMock.MyMethod(linkedMock);

    classMock.AssertWasCalled(c => c.MyMethod(linkedMock));
}

public class MyClass
{
    public virtual void MyMethod(MyClass linkedClass)
    {
        Console.WriteLine("MyMethod is called");
    }
}
person dh.    schedule 08.02.2010
comment
Как и вопрос, этот ответ меня смущает. Вы смешиваете Expect (используется для фазы записи в записи-воспроизведении-проверке) с AssertWasCalled (используется на этапе утверждения в аранжировке-действии-утверждении). Не следует смешивать оба подхода в одном тесте. - person Wim Coenen; 09.02.2010
comment
Это новый способ насмешки с использованием Rhino Mocks 3.5. Моки / заглушки, возвращаемые из MockRepository.GenerateMock () и MockRepository.GenerateStub (), возвращаются в режиме воспроизведения и не требуют явного перехода в режим воспроизведения. Посмотрите здесь ayende.com/Wiki/ - person dh.; 09.02.2010
comment
Я думаю, что wcoenen прав, вы должны либо использовать Expect, затем вызвать VerifyAllExpectations, либо просто AssertWasCalled. Нигде в предоставленной вами ссылке не делается Expect без того же VerifyAllExpectations или Expect и AssertWasCalled. - person Sam Holder; 09.02.2010
comment
В той же справке вы можете найти описание метода расширения Expect (), в котором говорится, что метод расширения Expect () создает новое ожидание для этого макета, которое необходимо проверить / подтвердить позже (с помощью VerifyAllExpectations () или AssertWasCalled ( ) методы). Поэтому на самом деле не имеет значения, какой из них вы выберете (здесь: ayende.com /Wiki/Rhino+Mocks+3.5.ashx#ExpectExtensionMethod) - person dh.; 09.02.2010
comment
В то же время я согласен с тем, что ожидание кажется излишним, поскольку не дает никакой дополнительной ценности тесту в свете утверждения. - person dh.; 09.02.2010

Ваш подход будет работать только в том случае, если ваш метод AddLink является виртуальным, иначе среда выполнения .Net всегда будет запускать реальную реализацию (и это правильно).

Обычно лучше всего использовать интерфейсы при внедрении зависимостей (так что ваш класс ожидает IMyClass вместо MyClass). Таким образом, намного проще использовать фреймворки mocking - вам не только не нужно помнить о том, чтобы делать все методы виртуальными, но вы избегаете проблем с передачей правильных аргументов в конструктор MyClass (что в реальном мире вызывает боль)

person Grzenio    schedule 08.02.2010