PATCH for restore fixtures data after every test running

rails的fixtures有一个令人讨厌的地方:

fixtures 的数据不会在测试结束后自动清除 ,这样就使得fixtures遗留的数据影响到后来的测试。

相关的争论也持续了很久 ,具体的连接请看  http://dev.rubyonrails.org/ticket/2404

里面的 Rick的patch我在rspec下用了,不见好用,我只能自己搞了一个patch,在rspec的 spec_helper.rb下引入
,解决了这个问题 。

patch主要的思路是: 每次测试setup运行前插入fixture的数据,保证这个插入 fixtures数据的事务和test运行时的事务是同一个 ,teardown结束前,清空一些类变量, 原有的teardown运行的时候会作事务回滚的动作,这样就可以保证每次测试都回滚圆来插入的 fixtures的数据。

相关的配置 :
  config.use_transactional_fixtures = true
  config.use_instantiated_fixtures  = false



module Test #:nodoc:
  module Unit #:nodoc:
    class TestCase #:nodoc:
      alias_method : old_setup_with_fixtures, :setup_with_fixtures unless method_defined?(: old_setup_with_fixtures)
      alias_method : old_teardown_with_fixtures, :teardown_with_fixtures unless method_defined?(: old_teardown_with_fixtures)
      def setup_with_fixtures

        if use_transactional_fixtures?

          ActiveRecord::Base.send :increment_open_transactions
          ActiveRecord::Base.connection.begin_db_transaction
          close_original_activerecord_transaction_methods
        end
        old_setup_with_fixtures
        if use_transactional_fixtures?
          open_original_activerecord_transaction_methods
        end
        
      
      end
      
      def teardown_with_fixtures
        if use_transactional_fixtures?
          clear_fixtures_states_when_use_transactional_fixtures
        end
        old_teardown_with_fixtures       
      end      
      #prevent the next code:alias_method from trigger invoking the self.method_added introspected method
      class<<TestCase
        alias old_method_added method_added
        def method_added(m) 
          #do nothing
        end
      end

      alias_method :setup,:setup_with_fixtures
      alias_method :teardown,:teardown_with_fixtures
      #reopen the introspector class method:method_added
      class<<TestCase
        alias method_added old_method_added
      		
      end
      
      private
      def clear_fixtures_states_when_use_transactional_fixtures
        @@already_loaded_fixtures.clear if @@already_loaded_fixtures
        @loaded_fixtures.clear if  @loaded_fixtures

      end
      def close_original_activerecord_transaction_methods
        self.class.class_eval(%Q[
          	class<<ActiveRecord::Base
          		alias old_increment_open_transactions increment_open_transactions
          		def increment_open_transactions
          			#do nothing
      			end
      		end
          ])
        ActiveRecord::Base.connection.class.class_eval(%Q[
          	alias_method : old_begin_db_transaction,:begin_db_transaction
          	def begin_db_transaction
          		#do nothing
      		end
          ])
        
      end
      
      def open_original_activerecord_transaction_methods
        self.class.class_eval(%Q[
          	class<<ActiveRecord::Base
          		alias increment_open_transactions old_increment_open_transactions
          		
      		end
          ])
        ActiveRecord::Base.connection.class.class_eval(%Q[
          	alias_method :begin_db_transaction,: old_begin_db_transaction
          	
          ])
      end
    end
  end
end

你可能感兴趣的:(cache,ActiveRecord,Rails,rspec)