2013-06-04 45 views
1

我寫我的應用程序的典型測試,我通過表單創建一個模型,檢查模型數等於1爲什麼這些Rspec示例不會在數據庫事務中發生?

因爲在測試DB已經多條記錄的測試失敗,該計每次運行我的測試時都會增加。看起來每個例子都不是在事務內部發生的(正在回滾),而且我不知道爲什麼。

我在spec_helper.rb文件,這是應該在一個事務中運行的每個例子這一行:

config.use_transactional_fixtures = true 

這裏是我的天賦,保持生成模型對象:

require 'spec_helper' 

describe "Admin artwork pages" do 
    subject { page } 
    let(:gallery) { FactoryGirl.create(:gallery) } 

    describe "artwork creation" do 
    context "with valid attributes" do 
     it "creates new artwork" do 
     visit admin_gallery_artworks_path(gallery_id: gallery.id) 

     click_link 'Add new artwork' 
     fill_in 'artwork_title', with: 'Still Life' 
     click_button 'Create Artwork' 

     page.should have_text 'Successfully created' 
     Artwork.count.should eq 1 
     end 
    end 
    end 
end 

這裏是來自Rspec的錯誤消息:

Failures: 

1) Admin artwork pages artwork creation with valid attributes creates new artwork 
Failure/Error: Artwork.count.should eq 1 

    expected: 1 
     got: 153 

    (compared using ==) 

編輯:我的spec_helper.rb文件的內容:

ENV["RAILS_ENV"] ||= 'test' 
require File.expand_path("../../config/environment", __FILE__) 
require 'rspec/rails' 
require 'rspec/autorun' 
require 'capybara/rails' 
require 'capybara/rspec' 

Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} 

RSpec.configure do |config| 

# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures 
config.fixture_path = "#{::Rails.root}/spec/fixtures" 

# If you're not using ActiveRecord, or you'd prefer not to run each of your 
# examples within a transaction, remove the following line or assign false 
# instead of true. 
config.use_transactional_fixtures = true 

# If true, the base class of anonymous controllers will be inferred 
# automatically. This will be the default behavior in future versions of 
# rspec-rails. 
config.infer_base_class_for_anonymous_controllers = false 

# Run specs in random order to surface order dependencies. If you find an 
# order dependency and want to debug it, you can fix the order by providing 
# the seed, which is printed after each run. 
#  --seed 1234 
config.order = "random" 
# Include route helpers 
config.include Rails.application.routes.url_helpers 
# 
# Take the FactoryGirl out of FactoryGirl.create 
config.include FactoryGirl::Syntax::Methods 

我使用Rails 4.0.0.rc1,紅寶石1.9.3,FactoryGirl和RSpec形軌道2.13.0感謝您的幫助。

+0

您使用的數據庫是? –

+0

Rails附帶的Sqlite3。 – hlh

+0

您是否在使用燈具? –

回答

0

我相信這個問題是你寫測試的方式,並且由於使用config.use_transactional_fixtures = true而減少了。重點是說(compared using ==)

嘗試使用預期變化rspec的語法,而不是

改變這種錯誤的底部:

click_button 'Create Artwork' 

    page.should have_text 'Successfully created' 
    Artwork.count.should eq 1 

要這樣:

expect { click_button 'Create Artwork' }.to change { Artwork, :count }.by(1) 

    page.should have_text 'Successfully created' 

讓我知道如果這有幫助

0

您正在運行請求規範:當y ou調用訪問被測代碼在服務器實例中運行(在相同的進程中)。特別是這意味着它使用了不同的線程。

因此,應用程序代碼最終使用不同的數據庫連接,並且由於事務是每個連接事件,因此當控制器將記錄插入數據庫時​​不會使用事務。

有幾種方法可以解決這個問題。一個是放棄rspec的交易裝置並使用database_cleaner gem。您可以進行設置,以便控制器和模型規範使用事務,但請求規範使用截斷來強制清除表。

另一種方法是嘗試強制規範代碼和服務器代碼使用相同的數據庫連接,這樣可以消除問題。您可以在this answer中看到此方法。根據我的經驗,這很有效,直到你開始使用水豚驅動程序,如poltergeist,它將在頁面上運行任何javascript,並且你的頁面會觸發ajax請求。

我一直在使用的方法是將活動記錄連接池大小設置爲1:只允許1個連接,所以每個人都會使用同一個連接。然後你必須做一些工作來確保連接返回到池中或者你的規範只是掛起。

我寫了細節前一陣子爲blog post,但簡而言之,你需要

  • 呼叫ActiveRecord::Base.clear_active_connections!調用像訪問方法之前,點擊等
  • 黑客config.middleware.insert_before ActiveRecord::ConnectionAdapters::ConnectionManagement,以便它在每次請求後清除連接(默認情況下它不會在測試中執行此操作)。
4

事實證明,Rails 4支持從rspec-rails 2.13.1開始 - 我使用的是2.13.0。升級後,規格發生在他們應該進行的交易中。

感謝大家花時間發佈幫助。

相關問題