Rails fragment cache testing with RSpec

前端 未结 3 480
生来不讨喜
生来不讨喜 2021-02-04 15:22

I feel like this is a not-so-much documented topic, at least I\'ve had a lot of trouble finding our about the best practices here.

I\'m fragment caching in the view usin

3条回答
  •  遥遥无期
    2021-02-04 15:32

    I use view specs to test cache expiration in views:

    describe Expire::Employee, type: :view, caching: true do
    
      def hour_ago
        Timecop.travel(1.hour.ago) { yield }
      end
    
      def text_of(css, _in:)
        Nokogiri::HTML(_in).css(css).text
      end
    
      let(:employee) { hour_ago { create :employee } }
    
      def render_employees
        assign(:employees, [employee.reload])
        render(template: 'employees/index.html.erb')
      end
      alias_method :employees_list, :render_employees
    
      context "when an employee's position gets changed" do
        let(:position) { create :position, employee: employee }
        before { hour_ago { position.update!(name: 'Old name') } }
        let(:update_position) { position.update!(name: 'New name') }
    
        it "should expire the employee's cache" do
          expect { update_position }
            .to change { text_of('.positions', _in: employees_list) }
            .from(/Old name/).to(/New name/)
        end
      end
    
      # similar spec case for home base assignment
    end
    

    where

    • Timecop gem is used to travel in time to make sure that cache key timestamps are different for different cache versions of employee
    • Nokogiri gem is used to extract employee position's text from the rendered view

    Note that I tagged this spec with caching: true. It enables caching before each test case and disables after it:

    config.before(:each, caching: true) do
      controller.perform_caching = true
    end
    config.after(:each, caching: true) do
      controller.perform_caching = false
    end
    

    And you might want to add an example that checks that an employee is being actually cached

    describe Expire::Employee, type: :view, caching: true do
      context 'with an uncached employee' do
        it 'should cache the employee' do
          expect_any_instance_of(Employee)
            .to receive(:current_positions).once
    
          2.times { render_employees }
        end
      end
    
      # other spec cases
    end
    

提交回复
热议问题