Factory Girl / Capybara deleting records from database mid-test?

前端 未结 4 1407
野趣味
野趣味 2021-02-19 10:10

Working with RSpec & Capybara, I\'m getting an interesting test failure mode which goes away with a few subtle rearrangements of lines in the test case...stuff that shouldn\

相关标签:
4条回答
  • 2021-02-19 10:20

    With the help of the Factory Girl mailing list I've found the issue.

    By default RSpec uses transactions to maintain the database in a clean state and each transaction is tied to a thread. Somewhere along the pipeline the visit_page command splits off and the transaction tied to the current thread dies.

    The solution is simple: disable transactions.

    describe "Sessions" do
      self.use_transactional_fixtures = false
    
       it 'no longer uses transactions' do
         #whatever you want
      end
    end
    

    Update for Rails 5.1

    As of Rails 5.1, use_transactional_fixtures is deprecated and should be replaced with use_transactional_tests.

    self.use_transactional_tests = false
    
    0 讨论(0)
  • 2021-02-19 10:31

    I think the user variable in RSpec has overwritten the one in the controller so it didn't work ? (couldn't get right user.email in the test)

    Before :

    user = Factory(:user)
    user.password! '2468'
    
    visit '/sessions/index' # user gets overwritten
    
    fill_in 'Email', :with => user.email # can't get user.email
    

    After :

    visit '/sessions/index' # Execute action
    
    user = Factory(:user) # user gets overwritten
    user.password! '2468'
    
    fill_in 'Email', :with => user.email  # user.email works
    
    0 讨论(0)
  • 2021-02-19 10:31

    This isn't technically an answer, more of a comment but to clarify the code it's the easiest mechanism.

    Can you try doing the following to help narrow down where the user's being destroyed

    describe "Sessions" do
      it 'allows user to login' do
        #line one
        user = Factory(:user)
        #For SO, this method hashes the input password and saves the record
        user.password! '2468'
    
    
    # check the user's definitely there before page load
    puts User.first
    
        #line two
        visit '/sessions/index'
    
    # check the user's still there after page load
    puts User.first.reload
    
    
        fill_in 'Email', :with => user.email
        fill_in 'Password', :with => '2468'
        click_button 'Sign in'
    
    # check the user's still there on submission (though evidently not)
    puts User.first.reload
    
        page.should have_content('Logged in')
      end
    end
    

    EDIT

    The fact that it works for you ok in real life but not in Capybara suggests that it may be a product of existing session information. When you're testing in the browser you're usually going off the back of previous work but Capybara is always starting from a clean session.

    You can easily see if you can reproduce the Capybara error in-browser by clearing all your cookies (as I'm sure you know) or by just switching to a new incognito window in Chrome/FF which is a nice quick way to get a clean session.

    0 讨论(0)
  • 2021-02-19 10:31

    The correct answer above helped me. Of course, I needed to change some other tests that (wrongly or rightly) assumed a fixture did not exist. For more information: there's some info about this in the Capybara README.

    https://github.com/jnicklas/capybara

    "If you are using a SQL database, it is common to run every test in a transaction, which is rolled back at the end of the test, rspec-rails does this by default out of the box for example. Since transactions are usually not shared across threads, this will cause data you have put into the database in your test code to be invisible to Capybara."

    You can also config RSpec to clean up after your test manually:

    https://github.com/jnicklas/carrierwave/wiki/How-to%3A-Cleanup-after-your-Rspec-tests

    0 讨论(0)
提交回复
热议问题