Должен ли я заглушить модель в Factory girl или в файле спецификаций во время тестирования?

Почти в каждом файле спецификации, с которым я сталкиваюсь, я заканчиваю тем, что пишу что-то вроде:

  before :each do
    @cimg = Factory.build :cimg_valid
    @cimg.stub(:validate_img).and_return true
    @cimg.stub(:validate_img_url).and_return true
    @cimg.stub(:save_images).and_return true
    @cimg.stub(:process_image).and_return true
    @cimg.stub(:img).and_return true
  end

Я имею в виду, что модель, которую я получаю от Factory.build, полностью действительна. Но если я не заглушу этот материал, он сохранит вещи в файловой системе и проверит вещи, которые я не тестирую...

Что я имею в виду, я думаю, было бы чище сделать что-то вроде этого:

  before :each do
    @cimg = Factory.build :cimg_for_testing_tags
  end

Если заглушка на Фабрике вообще возможна.

Как правильно заглушить модель?


person Zequez    schedule 30.01.2012    source источник


Ответы (4)


В последних версиях factory_girl у вас есть обратный вызов after_build, поэтому я считаю, что вы можете определить свою фабрику следующим образом:

FactoryGirl.define do
  factory :cimg_for_testing_tags do

    ... # Factory attributes

    after_build do |cimg|
      cimg.stub(:validate_img).and_return true
    end
  end
end

ОБНОВЛЕНИЕ

После factory_girl 3.3.0 синтаксис изменился на следующий:

FactoryGirl.define do
  factory :cimg_for_testing_tags do

    ... # Factory attributes

    after(:build) do |cimg|
      cimg.stub(:validate_img).and_return true
    end
  end
end
person fkreusch    schedule 31.01.2012
comment
Но должен ли я это делать? Или я должен заглушить это в файле спецификации? - person Zequez; 31.01.2012
comment
Я думаю, что если вы повторяетесь много раз, в этом случае имеет смысл иметь общую заглушку, просто убедитесь, что :cimg_for_testing_tags имеет родительскую фабрику, которая не заглушена для ситуаций, в которых вы хотите проверить фактическое поведение. - person fkreusch; 31.01.2012
comment
Это потрясающая техника. Я обнаружил, что борюсь с решением для таких ситуаций. Спасибо @fkreusch! - person josemota; 11.05.2012
comment
Это больше не работает. В последнем rspec это приведет к сбою "Using 'stub' from rspec-mocks' old ':should' syntax without explicitly enabling the syntax is deprecated." К сожалению, если вы переключитесь на использование нового синтаксиса rspec allow(), вы столкнетесь с другой проблемой, потому что FactoryGirl не включает методы RSpec: NoMethodError: undefined method 'allow' for #<FactoryGirl::SyntaxRunner:0x007f95469cc0d8>. Кто-нибудь знает решение этой проблемы, которое работает с последними версиями? - person Jazz; 05.12.2014
comment
Вы можете сделать def cimg.validate_img; true; end и эффективно заглушить его без rspec. - person Mladen Jablanović; 25.06.2015
comment
@Jazz Есть способ использовать синтаксис разрешения. Смотрите мой ответ. - person Ho-Sheng Hsiao; 30.06.2015

Ответ @fkreusch отлично работает, пока вы не используете новый синтаксис RSpec expect() (3.0+)

Включение этого в rails_helper.rb работает для меня:

FactoryBot::SyntaxRunner.class_eval do
  include RSpec::Mocks::ExampleMethods
end

В примере OP теперь вы можете сделать:

FactoryBot.define do
  factory :cimg_for_testing_tags do

    ... # Factory attributes

    after(:build) do |cimg|
      allow(cimg).to receive(:validate_img) { true }
    end
  end
end

Кредит: github.com/printercu, см.: https://github.com/thoughtbot/factory_bot/issues/703#issuecomment-83960003

person Ho-Sheng Hsiao    schedule 30.06.2015
comment
Выполнение того, что описано здесь, теперь вызывает следующую ошибку (FactoryGirl v4.7.0): The use of doubles or partial doubles from rspec-mocks outside of the per-test lifecycle is not supported. - person jsears; 29.09.2016
comment
@jsears Я столкнулся с этой ошибкой, потому что мой rails_helper.rb работал FactoryGirl.lint в блоке before(:suite), и там нельзя было установить заглушки. Я решил проблему, заключив вызов lint в RSpec::Mocks.with_temporary_scope { ... }. - person vergenzt; 29.11.2016
comment
Обратите внимание, что FactoryGirl теперь FactoryBot, поэтому в вашем примере эти два имени должны измениться. - person aardvarkk; 14.12.2017

Фабрика должна производить объекты «реального мира», поэтому изменение поведения (т.е. заглушки) на фабрике является плохой практикой (и подверженной ошибкам).

Ты можешь сделать

let(:user) instance_double(User, FactoryGirl.attributes_for(:user))

before do
  allow(user).to receive(:something).and_return('something')
end

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

person thisismydesign    schedule 05.09.2017

Вы также можете использовать FactoryGirl#build_stubbed.

person Su Zhang    schedule 06.06.2014