2012-02-12 14 views
5

私はモデルがあります:投稿とユーザー(Devise)。私はコントローラーポストをテストしています。RSpec、Devise、工場の女の子でコントローラをテストする

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 

しかし、第二のテストが失敗した:

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

私はこれをどのように修正すればよいですか?

答えて

7

テストの間にデータベースをクリーニングするツールが必要です。クリーンなデータベースを使用して各テストを実行できる必要があるためです。私はdatabase_cleanerを使用しています、それはかなり有名な宝石であり、それは本当にうまく動作します。セットアップも簡単です。 README(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

私はあなたのコードをspec_helperに含めます。エラーが発生しました。エラー/エラー:バックトレースから一致する行が見つかりません ActiveRecord :: StatementInvalid: SQLite3 :: SQLException:トランザクション内でトランザクションを開始できません。トランザクション開始トランザクション – Mike

+0

このために別の宝石は必要ありません。 – coneybeare

+3

SQLiteの例外解決策が 'clean_with(:truncation)'を削除し、ストラテジを 'DatabaseCleaner.strategy =:truncation'に完全に変更することでした – Dan

9

このために別の宝石は必要ありません。 FactoryGirlにはこのための動的ヘルパーが組み込まれています。私はこれについて短いRailscastを見てみることをお勧めします。これはどのように動作するかのスニペットです:

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

hmmm、有料コンテンツへのリンク...ほとんどのようには見えません回答の参考にしてください... – botbot

+18

レールデベロッパーでRailcastを使用していない場合は間違っています。 – coneybeare

+0

TRUE Railsデベロッパーの方はまず無料のコンテンツにリンクし、有料のものを提案する必要があります – Aleks