2012-02-12 7 views
5

J'ai des modèles: Post et User (Devise). Je suis en train de tester le contrôleur Post.Test du contrôleur avec RSpec, Devise, 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 

Mais le second test échoue:

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

Comment puis-je résoudre ce problème?

Répondre

7

Vous avez besoin d'un outil pour nettoyer votre base de données entre les tests. Parce que vous devriez pouvoir exécuter chaque test avec une base de données propre. J'utilise database_cleaner, c'est une gemme assez célèbre et ça marche très bien. C'est facile à configurer aussi. Un exemple du README (lié à RSpec):

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

Lorsque j'inclus votre code dans spec_helper. J'ai une erreur Erreur/Erreur: Impossible de trouver la ligne correspondante du backtrace ActiveRecord :: StatementInvalid: SQLite3 :: SQLException: impossible de démarrer une transaction dans une transaction: commencez la transaction – Mike

+0

vous n'avez pas besoin d'une autre gemme pour cela. – coneybeare

+3

J'ai trouvé la solution d'exception SQLite était de supprimer le 'clean_with (: troncature)' et de changer complètement la stratégie à 'DatabaseCleaner.strategy =: truncation' – Dan

9

Vous n'avez pas besoin d'une autre gemme pour cela. FactoryGirl a construit des aides dynamiques pour cela. Je suggère de regarder le court Railscast à ce sujet. Voici un extrait de son fonctionnement:

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

hmmm, un lien vers le contenu payant ... ne semble pas le plus utile des réponses ... – botbot

+18

Si vous êtes un développeur de rails et n'utilisez pas Railcasts, alors vous vous trompez. – coneybeare

+0

mais si vous êtes un développeur TRUE Rails, vous devez d'abord créer un lien vers du contenu gratuit, puis proposer le contenu payant – Aleks

Questions connexes