2012-01-30 7 views
20

Quasi ogni file spec vengo dall'altra parte io alla fine a scrivere cose del genere:Devo stubare il modello in Factory girl o nel file spec durante il test?

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 

Voglio dire, il modello che ricevo da Factory.build è del tutto valido. Ma se non stub quella roba salva le cose nel file system, e convalida roba non sto testando ...

Quello che voglio dire, penso che sarebbe stato più pulito di fare qualcosa di simile:

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

Se lo stub in fabbrica è possibile.

Qual è il modo corretto di eseguire lo stub del modello?

risposta

20

Nelle versioni recenti di factory_girl si dispone di un callback after_build, quindi credo che si potrebbe definire la fabbrica in questo modo:

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 

UPDATE

Dopo factory_girl 3.3.0, la sintassi è cambiato a seguito:

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 
+3

Ma * dovrei farlo *? O dovrei stub nel file spec? – Zequez

+2

Penso che se ti stai ripetendo molte volte, avendo in questo caso uno stub generale ha senso, assicurati che: cimg_for_testing_tags abbia una factory madre che non viene definita per le situazioni in cui vuoi testare il comportamento reale. – fkreusch

+0

Questa è una tecnica fantastica. Mi sono trovato a dover lottare con una soluzione per questo tipo di situazioni. Grazie @fkreusch! – josemota

25

@ risposta di fkreusch grandi opere fino a quando si utilizza il nuovo RSpec expect() sintassi (3.0+)

Mettendo questo in rails_helper.rb opere per me:

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

Nell'esempio del PO, ora è possibile farlo:

FactoryGirl.define do 
    factory :cimg_for_testing_tags do 

    ... # Factory attributes 

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

credito: github.com/printercu, vedi: https://github.com/thoughtbot/factory_girl/issues/703#issuecomment-83960003

+3

Fare ciò che è descritto qui ora genera il seguente errore (FactoryGirl v4.7.0): '' 'L'uso di doppi o doppi parziali da rspec-mock al di fuori del ciclo di vita per test non è supportato. '' ' – jsears

+0

@jsears stavo incontrando quell'errore perché il mio' rails_helper.rb' stava eseguendo 'FactoryGirl.lint' in un blocco' before (: suite) ', e non è possibile impostare stub lì. Ho risolto il problema avvolgendo la chiamata lint in 'RSpec :: Mocks.with_temporary_scope {...}'. – vergenzt

+0

Nota che 'FactoryGirl' è ora' FactoryBot', quindi questi due nomi dovrebbero cambiare nel tuo esempio. – aardvarkk

1

Una fabbrica dovrebbe produrre oggetti del "mondo reale", quindi è una cattiva pratica (e incline agli errori) modificare il comportamento (ad es. mozzicone) in una fabbrica.

Si può fare

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

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

e se la vostra clausola before diventa troppo grande si consiglia di estrarre in un metodo separato o creare una classe figlia finta che sostituisce i metodi che si desidera stub.