2011-05-06 40 views
13

我有一個Spork測試服務器的問題。rspec,factory_girl和datamapper spork和cache_classes問題

如果我在config/environments/test.rb中設置了config.cache_classes = false,那麼規格開始出現rasie錯誤。

Failure/Error: task = Factory(:something, :foo => @foo, :bar => @bar) 
    DataMapper::ImmutableError: 
     Immutable resource cannot be modified 

這是我spec_helper.rb:

require 'spork' 

Spork.prefork do 
    if ENV['CODE_COVERAGE'] == '1' 
    require 'simplecov' 
    SimpleCov.start 'rails' 
    end 

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

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

    RSpec.configure do |config| 
    config.mock_with :mocha 
    config.include Rails.application.routes.url_helpers 
    config.include UrlHelper 

    config.before(:each) do 
     repository(:default) do 
     transaction = DataMapper::Transaction.new(repository) 
     transaction.begin 
     repository.adapter.push_transaction(transaction) 
     end 
    end 

    config.after(:each) do 
     repository(:default).adapter.pop_transaction.try(:rollback) 
    end 

    end 
end 

# This code will be run each time you run your specs. 
Spork.each_run do 
    # reload factories 
    Factory.definition_file_paths = Dir[File.join(Rails.root, "spec", "factories")] 
    Factory.find_definitions 

    DatabaseCleaner.strategy = :truncation 
    DatabaseCleaner.clean 
    LoggedEvent.all.destroy! 

end 

當我有config.cache_classes = true,則一切正常,但它不會重新加載我一個模型,控制器類,所以我不在這種情況下,請注意使用spork。

我試圖添加到spec_helper.rb這樣的事情,當緩存爲真:

Spork.each_run do 
    Dir.glob("#{Rails.root}/app/models/*.rb").sort.each { |file| load file } 
end 

但我不喜歡這種解決方案。

回答

20

只需添加:

ActiveSupport::Dependencies.clear 

到的prefork塊的結束。這將負責清理模型。

另外,您希望將rspec配置包含移至Spork.each_run,同樣需要spec支持和共享文件。

這個工程,我用這個設置在2個項目w/o任何麻煩。

+3

等待,ActiveSupport :: Dependencies.clear屬於prefork或each_run嗎?我看到了相互衝突的故事。這兩者似乎都不適合我,都會導致加載問題:「預計xxxx會定義xxxx」。另外,單獨解決問題是否是'ActiveSupport :: Dependencies.clear'?還是需要與原始問題中的each_run示例結合使用? – 2011-11-14 15:20:44

+0

我不知道爲什麼,但我的項目只是突然開始這樣做,沒有明顯的原因。我最終將Dependencies.clear放入我的Spork.each_run中,並且它對我有用。我沒有我的Rspec.config在each_run中,只是:FactoryGirl.reload和ActiveSupport :: Dependencies.clear。希望有所幫助。 – 2011-11-29 18:58:47

+0

ActiveSupport :: Dependencies.clear應該添加在prefork的末尾,而不是each_run – Ran 2011-12-01 09:48:36

8

嘗試ActionDispatch :: Reloader

除了config/environments/test.rb設置config.cache_classes = false,下面似乎讓DataMapper的和叉勺發揮很好了我們的團隊:

Spork.each_run do 

    # Routes 
    MyApp::Application.reload_routes! 

    if Spork.using_spork? 
    # Reload all app files 
    ActionDispatch::Reloader.cleanup! 
    ActionDispatch::Reloader.prepare! 

    # All factories 
    FactoryGirl.reload 
    end 

end 
+0

不錯。我沒有想到它,但這似乎解決了我與Mongoid和Spork的問題。關於該主題的所有其他文檔([Spork.trap_method Jujitsu](https://github.com/sporkrb/spork/wiki/Spork.trap_method-Jujitsu)和「ActiveSupport :: Dependencies.clear」)在所有。我甚至能夠擺脫我在Rails :: Mongoid.load_models上的額外陷阱。 – 2012-10-01 23:41:53

+1

這種方法實際上包括ActiveSupport :: Dependencies.clear等。調用ActionDispatch :: Reloader.cleanup!並準備!正是什麼重新加載!在軌道控制檯中。 +1 – 2013-05-16 03:11:01

0

您好我想分享什麼幫助我再次運行測試。
事實證明,我不得不添加shared_connection的技巧,因爲spork抱怨連接丟失。
在此之後,我不得不在塊的末尾移動dependency.clear行,因爲它正在緩存我的模型。

Spork.each_run do 
    # ActiveSupport::Dependencies.clear # <-- moved this line at end of block as suggested by @solnic 
    ActiveRecord::Base.instantiate_observers 
    MyApp::Application.reload_routes! 
    FactoryGirl.reload 

    class ActiveRecord::Base 
    mattr_accessor :shared_connection 
    @@shared_connection = nil 

    def self.connection 
     @@shared_connection || retrieve_connection 
    end 
    end 
    ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection 

    ActiveSupport::Dependencies.clear # <-- line moved here 

end if Spork.using_spork?