2015-06-19 4 views
1

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

Данные, которые мне нужны в объекте Stripe, захоронены, поэтому мне нужно было бы сделать event.data.object.date.lines.first.id. Я не уверен, как насмехаться/заглушить это ...

Единственный способ, которым я могу это сделать, - создать фальшивую модель, имитирующую объект события Stripe (в этом примере для меня помните, что Stripe события не могут быть созданы пользователем). И тогда я могу издеваться над этой поддельной моделью. Но действительно ли это способ сделать это? Есть ли способ, которым я могу просто использовать Rspec, чтобы заглушить весь shebang и сказать, что event.data.object.date.lines.first.id, где бы он ни появлялся, нужно просто перенастроить 1?

О, а также ... если нет, и получается, что мне нужно создать поддельную модель ... советы очень ценятся, потому что прямо сейчас я думаю, что эта «поддельная» модель нуждается во многих слоях детей, и полностью не стоит затрат времени.

ответ

0

RSpec не предоставляет никаких специальных механизмов для доступа к элементам испытываемых, да так, что вам нужно будет каким-то образом stub метод id и он вернуть все, что вы хотите (например 1).

Для этого у вас должен быть способ доступа к объекту event в вашем тесте, чтобы вы могли заглушить его метод data. Как только вы сможете получить к нему доступ, вы можете использовать сопоставление RSpec receive_message_chain, чтобы указать последовательность методов, для которых, если вызвано, вы вернетесь 1.

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

Если это невозможно, вы можете определить класс event и использовать метод allow_any_instance_of для заглушки data. Полученный макет будет выглядеть следующим образом, предполагая, что Foo был класс event объекта вы обеспокоены:

allow_any_instance_of(Foo)).to receive_message_chain(
    :data, :object, :date, :lines, :first, :id).and_return(1) 

Вот тест, который проходит:

module Stripe 
    class Event ; end 
end 
describe 'stack overflox example' do 
    it 'should pass' do 
    event = Stripe::Event.new 
    expect(event).to receive_message_chain(:data, :object, :date, :lines, :first, :id).and_return(23) 
    expect(event.data.object.date.lines.first.id).to eq(23) 
    end 
end 
+0

Так что мне нужно пойти с опцией 2. Класс события = 'Stripe :: Event'. Если я попробую 'allow (any_instance_of (Stripe :: Event)) to receive_message_chain (: data,: object,: date) .and_return (Date.today)', я получаю 'undefined method' any_instance_of 'для # '. И если я попробую, 'Stripe :: Event.any_instance.stub_chain (: data,: object,: date) .and_return (Date.today)', я получаю 'Stripe :: Event не реализует # data' – james

+0

Извините, я Смешанные старые и новые методы RSpec. Я обновил ответ, чтобы отразить текущий метод., Тем не менее, учитывая сообщение об ошибке, которое вы сообщили, «событие» не является экземпляром 'Stripe :: Event' или' Stripe :: Event', не определяет метод экземпляра 'date'. –

+0

Еще одно: методы 'stub ...' RSpec проверяют, определяет ли класс этот метод. Я подозреваю, что 'Stripe' динамически определяет метод' data', поэтому вы сталкиваетесь с этим. Попробуйте пересмотренную версию в моем ответе, которая не проходит через эту проверку «stubbing». –

1

В этой конкретной ситуации с полоской, Я бы выбрал насмешку, используя библиотеку вместо создания заглушек с RSpec. Я использовал и предлагаю stripe-ruby-mock.

Преимущество такого подхода заключается в том, что вы более глупо смеетесь над тем, как работает Stripe, и вы можете switch to the actual stripe test api very easily.

+0

Oh Я не знал об этой библиотеке, спасибо, что указал на это! – james