2012-02-12 8 views
5

Mam modele: Post i User (Devise). Testuję kontroler Post.Testowanie kontrolera za pomocą 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 

Ale drugi test nie powiedzie się:

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

Jak mogę rozwiązać ten problem?

Odpowiedz

7

Potrzebujesz narzędzia do czyszczenia bazy danych między testami. Ponieważ powinieneś być w stanie uruchomić każdy test z czystą bazą danych. Używam database_cleaner, jest to dość znany klejnot i działa bardzo dobrze. Łatwo też skonfigurować. Przykład z README (powiązany z 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

Kiedy dołączę twój kod do spec_helper. Wystąpił błąd Niepowodzenie/Błąd: Nie można znaleźć pasującej linii z śledzenia wstecznego ActiveRecord :: StatementInvalid: SQLite3 :: SQLException: nie można uruchomić transakcji w ramach transakcji: rozpocznij transakcję – Mike

+0

nie potrzebujesz do tego innego klejnotu. – coneybeare

+3

Stwierdziłem, że rozwiązaniem wyjątku SQLite było usunięcie 'clean_with (: truncation)' i zmiana strategii całkowicie na 'DatabaseCleaner.strategy =: truncation' – Dan

9

Nie potrzebujesz do tego innego klejnotu. FactoryGirl ma wbudowane w to dynamiczne pomocniki. Proponuję obejrzenie krótkiego Railscast na ten temat. Oto krótki opis działania:

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

hmmm, link do płatnej treści ... nie wydaje się być najbardziej pomocne odpowiedzi ... – botbot

+18

Jeśli jesteś programistą szyn i nie używasz Railcasts, robisz to źle. – coneybeare

+0

, ale jeśli jesteś deweloperem TRUE Rails, powinieneś najpierw utworzyć link do darmowej zawartości, a następnie zasugerować płatną – Aleks