2009-10-18 3 views
3

Я пытаюсь использовать rspec в издевательстве, чтобы установить ожидания, которые я могу проверить в методах «должен» ... но я не знаю, как это сделать ... когда я вызываю методы .should_receive на макет , он проверяет ожидаемый вызов, как раньше: все методы завершаются.rspec mocks: проверить ожидания в нем «должны» методы?

вот небольшой пример:

describe Foo, "when doing something" do 
before :all do 
    Bar.should_recieve(:baz) 
    foo = Foo.new 
    foo.create_a_Bar_and_call_baz 
end 

it "should call the bar method" do 
    # ??? what do i do here? 
end 
end 

Как я могу проверить, ожидаемый вызов метода «он„должен“»? мне нужно использовать mocha или другую насмешливую структуру вместо rspec? или ???

ответ

8

Я собираюсь сделать еще один удар, потому что из первоначального набора ответов и ответов ясно видно, что было какое-то замешательство в том, что вы пытаетесь выполнить. Сообщите мне, если это ближе к тому, что вы пытаетесь сделать.

describe Foo, "when frobbed" do 
    before :all do 
    @it = Foo.new 

    # Making @bar a null object tells it to ignore methods we haven't 
    # explicitly stubbed or set expectations on 
    @bar = stub("A Bar").as_null_object 
    Bar.stub!(:new).and_return(@bar) 
    end 

    after :each do 
    @it.frob! 
    end 

    it "should zap a Bar" do 
    @bar.should_receive(:zap!) 
    end 

    it "should also frotz the Bar" do 
    @bar.should_receive(:frotz!) 
    end 
end 

Кстати, хотя это работает, я не большой поклонник Bar.stub!(:new) рисунка; Обычно я предпочитаю передавать соавторы через необязательные аргументы, например. @it.frob!(@bar). Когда не задан явный аргумент (например, в производственном коде), соавтор может быть по умолчанию: def frob!(bar=Bar.new). Это приводит к тому, что тесты немного меньше связаны с внутренней реализацией.

+0

спасибо, Авди. после: каждый работает хорошо. Я соглашаюсь с бит инъекции зависимости. вот как я справляюсь с этим в C# ... все еще изучая, что делает/не хорошо переводит в рубине. –

1

Как правило, вы никогда не должны ставить математическое ожидание в блоке before. Блоки before предназначены для настройки состояния, которое разделяется несколькими примерами (it блоков). Поместите ожидание в пример. Например .:

describe Foo, "when doing something" do 
    before :all do 
    @foo = Foo.new 
    end 

    it "should call the bar method" do 
    Bar.should_recieve(:baz) 
    @foo.create_a_Bar_and_call_baz 
    end 
end 

Я вообще стараюсь иметь мой describe блок описания конкретного состояния (например, describe Car, "given a full tank of gas"), а не описывая действие.

+0

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

 describe Foo, "when..." do it "should do this" it "should do that" it "should do another thing" end 
Я предполагаю, что я мог бы сделать раньше: каждый в этом случае, но это было бы провести существенные увеличения времени, чтобы выполнить свои тесты функционала/интеграции из-за сброс состояния внешних ресурсов и т.д. могут RSpec-х псевдотрансфицированные не справиться что я хочу? если нет, может мокко? –

+0

Derick, если я правильно понимаю вашу проблему, я считаю, что это может быть сценарий, в котором я использовал «после: каждый» для хорошего эффекта. Таким образом, у меня был бы блок «after: each», который вызывал тестируемый метод, и я бы установил другое ожидание в каждом блоке 'it'. – Avdi

+0

Кроме того, судя по предыдущему вашему вопросу, мне любопытно, знакомы ли вы с заглушками против насмешек? Заготовки похожи на 'should_receive', только они не задают ожиданий, они просто заглушают какое-то поведение. Нет ничего плохого в настройке заглушек в блоке 'before: every'. См. Здесь для получения дополнительной информации: http://rspec.info/documentation/mocks/stubs.html – Avdi

0

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

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

+0

Я понимаю, о чем вы говорите, и я согласен с этим. пример, который я показал здесь, слишком упрощен. реальная ситуация, с которой я имею дело, имеет класс, который я тестирую, и класс, который мне нужно высмеять. класс, который мне нужно высмеять, вызывается дважды во время выполнения одного метода в тестируемом классе - один раз для «запуска» и один раз «exec!» ... это SSH-соединение/выполнение команды. –

+0

проблема, с которой я столкнулся с ожиданием в блоке «it», заключается в том, что мне потребуется вызвать метод «foo.create_a_Bar_and_call_baz» (из приведенного выше примера) в каждом блоке «it», что является уродливым и трудным поддерживать. Я прихожу к этому из опыта C# /. NET BDD с Rhino Mocks, где я всегда задавал ожидания макета в блоках 'it', но я только один раз запускаю тестируемый класс в настройке. Я ожидаю, что смогу сделать подобные вещи с макетными объектами в рубине. это имеет смысл, и его следует поддерживать. ... или я снова покинул свой рокер? –

1

Метод should_receive используется для настройки вашего макетного объекта, чтобы вернуть что-то конкретное при вызове метода. Вот пример:

Bar.should_recieve(:baz).with.({:arg1 => 'this is arg1', :arg2 => 'this is arg2'}).and_return(true) 

Как правило, с BDD вы хотите проверить поведение своего приложения. Тестирование того, какие методы были вызваны для построения правильного поведения, не имеет значения. Если однажды вы решите удалить метод baz, вам придется обновлять свои тесты, даже если поведение вашего приложения не изменится.

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

+0

Я согласен, что мы хотим проверить поведение. Я не согласен с вашим заключением, что вызовы методов не являются поведением. иногда поведение тестируемого класса известно только тем, какие методы вызывают на другом объекте. если бы я не тестировал эти вызовы, тогда я бы тестировал только данные getter/setter (свойства, атрибуты и т. д.), которые вообще не тестировали бы поведение. Кажется, что rspec mocks не поддерживает утверждение ожиданий вне установки ожидания, что является отказом rspec, а не тем, как я тестирую. Я, вероятно, переключится на mocha –

+0

Я использовал Mocha и RSpec mocks (которые основаны на flexmock) широко. Насколько я знаю, они функционально эквивалентны; в некоторых случаях RSpec может быть более мощным. Я думаю, что есть, вероятно, лучший способ добиться того, что вы пытаетесь сделать. – Avdi

1

Я знаю, что это старый разговор, но только в случае, если кто-то еще нужен правильный ответ, здесь я пишу пример о том, как проверить rpec издевается spectations:

require 'spec' 
require 'spec/mocks' 
include Spec::Mocks::ExampleMethods 

o = mock('object') 
o.should_receive(:respond_to?).once 

space = Spec::Mocks::Space.new 
space.add o 

# here we should invoke methods, o.respond_to?:foo for instance 

space.verify_all 

приветствий