Ruby + Rspec + OpenStruct странное поведение
Так что я испытываю это странное поведение во время тестирования рубинового класса. Я использую rspec 3, чтобы проверить это, кстати.
Класс Foo имеет метод fetch_object, который вызывает метод find из класса Bar для извлечения объекта, а затем вызывает метод fail из извлеченного объекта.
Так называемое странное поведение происходит, когда я ожидаю получить метод "fail" один раз и не получить ни одного, но если я изменю имя метода на "faill", это работает как чудо:S
вот драма:
require 'ostruct'
class Foo
def fetch_object
foobar = Bar.find
foobar.fail
end
end
class Bar
def self.find
OpenStruct.new(name: 'Foo Bar')
end
end
describe Foo do
subject { Foo.new }
let(:foo) { OpenStruct.new() }
before do
expect(Bar).to receive(:find).and_return(foo)
end
it 'fetch object with name' do
expect(foo).to receive(:fail)
subject.fetch_object
end
end
1 ответ
Я подозреваю, что это потому, что вы устанавливаете ожидание для объекта, поведение которого зависит method_missing
(OpenStruct
).
По этой причине я бы не хотел использовать его как макет, я бы использовал обычный макет (и спецификация пройдет):
let(:foo) { double('foobar') }
Вы тестируете здесь, если возвращаемый объект (результат Bar.find) получит ожидаемое сообщение, не вдаваясь в детали реализации.
Установка ожиданий для динамических классов, таких как ostruct, может привести к странным результатам. Кажется, что в какой-то момент Kernel#fail
метод вызывается, таким образом, изменяя имя на faill
или любой другой, который еще не "взят" ядром, заставит его работать.
Другим решением будет использование OpenStruct, чтобы избежать method_missing
быть названным:
class OpenStruct
def fail
true
end
end
class Foo
def fetch_object
foobar = Bar.find
foobar.fail
end
end
class Bar
def self.find
OpenStruct.new(name: 'Foo Bar')
end
end
describe Foo do
subject { Foo.new }
let(:foo) { OpenStruct.new }
before do
expect(Bar).to receive(:find).and_return(foo)
end
it 'fetch object with name' do
expect(foo).to receive(:fail)
subject.fetch_object
end
end
Но я не знаю, почему вы хотите это сделать;)
Дополнительная информация: Двойники и динамический класс