Из документации rspec expect_any_instance_of()
устарело. Однако я пока не нашел простого способа заменить этот метод другим. Все, что я пробовал до сих пор, терпит неудачу, и особенно, вызывается метод, который, как ожидается, будет смоделирован.
context 'test Foo' do
before(:each) do
info = double(
size: 12345,
close: true
)
allow(Blah).to receive(:open).and_return(info) # this one works
end
it 'returns false on failure' do
# This expect_any_instance_of() works like a charm
expect_any_instance_of(MyUploader).to receive(:process_with_some_tool).and_return(false)
uploader = MyUploader.new(create(:my_object, data: nil))
# These expect()'s fails
expect(MyUploader).to receive(:process_with_some_tool).and_return(true)
expect(uploader).to receive(:process_with_some_tool).and_return(true)
uploader.store!(trigger_data)
end
end
Первый expect(MyUploader)
(то же самое с именем класса), я также пытался поместить внутрьблок before
. Я как бы ожидал, что он все равно потерпит неудачу, так как имя класса объекта uploader
выглядит следующим образом (и, конечно, число меняется при каждом запуске):
MyUploader::Uploader47181996911040
Однако я неЯ не понимаю, почему expect(uploader)
(то есть с объектом, который я только что выделил) тоже не работает. Поскольку я привязан к самому созданному мною объекту, почему бы ему не высмеять это событие :process_with_some_tool
и просто вернуть true
?
У меня есть puts "CALLED\n"
в моем :process_with_some_tool
, и яувидеть это сообщение, когда я использую expect()
. Я не вижу его, когда использую expect_any_instance_of()
. Так что первый ничего не высмеивает, а второй насмехается, как и ожидалось ...
Я также попытался обернуть голову вокруг справочной страницы Method , но, опять же, я несмог заставить его работать.
Итак, мой вопрос: как мы можем преобразовать expect_any_instance_of()
, чтобы он действительно работал?
Примечание: я новичок в Ruby, Rails, RSpec и все такое. Я подозреваю, что это легко, но я просто не понимаю, как заставить все это работать ...
Реализация проприетарна, но вот базовое представление того, что я использую:
class MyUploader < CarrierWave::Uploader::Base
include Inspectable
version :cleanup do
process :func1
process :func2
process :func3
after :store, :check_size
end
def func1
# Do work
end
def func2
if info.close
tmpfile = 'temp_file1.ext'
successful_processing = process_with_some_tool1(tmpfile)
log "message 1" unless successful_processing
end
if !info.close
tmpfile = 'temp_file2.ext'
successful_processing = process_with_some_tool2(tmpfile)
log "message 2" unless successful_processing
end
end
def func3
# Do work
end
def process_with_some_tool1(tmpfile)
puts "TOOL1 RUN"
system %Q{mytool1 -a -b -c "#{tmpfile}"}
end
def process_with_some_tool2(tmpfile)
puts "TOOL2 RUN"
system %Q{mytool2 -a -b -c "#{tmpfile}"}
end
def check_size
begin
if size < 100
raise "Too small"
end
rescue => error
log "some message"
end
end
end
Это базовое представление о том, что у меня есть. Код является частным, поэтому я не могу просто скопировать и вставить все это.
Я вижу сообщение "TOOL2 RUN"
, когда я ожидаю, что один (и tool1) будет заглушкой из-за expect()
.
Обратите внимание, что я не вижу, чтобы store
был реализован здесь. Итак, оно исходит из базового класса.
Обновление:
Я вижу, что store!()
вызывает cache()
, и это вызывает versions!()
, а реализация versions!()
включаетследующая функция инициализации:
def build_version(name, options)
uploader = Class.new(self)
const_set("Uploader#{uploader.object_id}".gsub('-', '_'), uploader)
uploader.version_names += [name]
...snip...
end
Как мы видим, эта функция создает новый класс и называет его «Uploader <#id>», что я и вижу, когда я печатаю class / object_id в консоль.
Проверяя все идентификаторы, теперь я вижу, что реальный объект, использованный в тесте, - это тот, который создан Class.new()
, а не тот, который я создаю в своем коде.
This build_version
метод происходит от ~/.rvm/gems/ruby-2.5.3/gems/carrierwave-0.11.0/lib/carrierwave/uploader/versions.rb
. Это часть функции загрузчика, которая кэширует файлы для ваших тестов. Похоже, что он не ограничивается кэшированием файлов, хотя ... Теперь мне интересно, получу ли я доступ к этому кешированному объекту, и мне будет позволено вместо этого присоединить мой expect()
или allow()
к этой версии. Я специально уточню у Carrierwave реализации 1066 *. Скорее всего, у них будет решение этой проблемы.