Трябва ли да премахна модела във 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