2012-02-12 3 views
5

I modelli sono: Post e Utente (Idea). Sto testando il controller Post.Test del controller con RSpec, Idea, Factory Girl

describe "If user sign_in" do 

    before(:all){ 
    @user = Factory(:user) 
    } 

    it "should get new" do 
    sign_in @user 
    get 'new' 
    response.should be_success 
    response.should render_template('posts/new') 
    end 

    it "should create post" do 
    sign_in @user 
    post 'create', :post => Factory(:post) 
    response.should redirect_to(post_path(:post)) 
    end 
end 

Ma la seconda prova fallisce:

Failure/Error: post 'create', :post => Factory(:post) ActiveRecord::RecordInvalid: Validation failed: Email has already been taken, Email has already been taken, Username has already been taken

Come posso risolvere questo problema?

risposta

7

È necessario uno strumento per pulire il database tra i test. Perché dovresti essere in grado di eseguire ogni test con un database pulito. Sto usando database_cleaner, è una vera gemma famosa e funziona davvero bene. È facile da configurare anche. Un esempio dal README (RSpec related):

RSpec.configure do |config| 

    config.before(:suite) do 
    DatabaseCleaner.strategy = :transaction 
    DatabaseCleaner.clean_with(:truncation) 
    end 

    config.before(:each) do 
    DatabaseCleaner.start 
    end 

    config.after(:each) do 
    DatabaseCleaner.clean 
    end 

end 
+3

Quando includo il codice in spec_helper. Ho ricevuto un errore Errore/Errore: impossibile trovare la linea corrispondente da backtrace ActiveRecord :: Istruzione non valida: SQLite3 :: SQLException: impossibile avviare una transazione all'interno di una transazione: iniziare la transazione – Mike

+0

non è necessario un altro gioiello per questo. – coneybeare

+3

Ho trovato che la soluzione di eccezione di SQLite consisteva nel rimuovere il 'clean_with (: truncation)' e cambiare completamente la strategia in 'DatabaseCleaner.strategy =: truncation' – Dan

9

Non hai bisogno di un altro gioiello per questo. FactoryGirl ha creato aiutanti dinamici per questo. Suggerisco di guardare il breve Railscast su questo. Ecco un frammento di come funziona:

FactoryGirl.define do 
    factory :user do 
    sequence(:username) { |n| "foo#{n}" } 
    password "foobar" 
    email { "#{username}@example.com" } 
+1

hmmm, un collegamento al contenuto a pagamento ... non sembra il più utile per le risposte ... – botbot

+18

Se sei uno sviluppatore di rotaie e non usi Railcast, allora stai sbagliando. – coneybeare

+0

ma se sei uno sviluppatore TRUE Rails, dovresti prima collegare il contenuto gratuito e poi suggerire quello a pagamento – Aleks