문제

Using the Railscast example, I have written a spec for my presenter which includes ActionView::TestCase::Behavior and passes in the view method to the presenter.

spec/spec_helper.rb:

  ... 
  config.include ActionView::TestCase::Behavior, :example_group => {:file_path => %r{spec/presenters}}
  ...

spec/presenters/order_presenter_spec.rb:

  require 'spec_helper'

  describe OrderPresenter do

    describe "#subtotal" do
      subject { OrderPresenter.new(order, view).subtotal }

      let(:order) { stub(:order, working_subtotal: 4500) }

      it "renders the subtotal table row" do
        should == "<tr><th>SUBTOTAL</th><td>$45.00</td></tr>"
      end
    end
  end

However, this gave me two errors. The first was

  /Users/shevaun/.rvm/gems/ruby-1.9.3-p392/gems/actionpack-3.2.13/lib/action_controller/test_case.rb:12:in `block in <module:TemplateAssertions>': undefined method `setup' for #<Class:0x007fe2343b2f40> (NoMethodError)

so I included ActiveSupport::Testing::SetupAndTeardown in the same way as ActionView::TestCase::Behavior.

Fixing that gave me the error:

  NoMethodError:
   undefined method `view_context' for nil:NilClass

when calling view. This is caused by the @controller instance variable inside ActionView::TestCase being nil.

I am using Rails 3.2.13 and rspec-rails 2.13.0 and have another application using the same versions which just works.

The only thing I can think of that might make a difference is that this app is using MongoDB so maybe the ActiveRecord application includes something which sets up @controller for free?

I have got a workaround which makes the presenter specs pass, but I would like to know how @controller normally gets instantiated, and if there's a more elegant way to do this for a MongoDB project (if it is ActiveRecord that's doing the magic).

도움이 되었습니까?

해결책

My current solution is to instantiate the @controller instance variable by calling setup_with_controller before the presenter specs.

spec_helper.rb:

RSpec.configure do |config|
  config.include ActiveSupport::Testing::SetupAndTeardown, :example_group => {:file_path => %r{spec/presenters}}

  config.include ActionView::TestCase::Behavior, :example_group => {:file_path => %r{spec/presenters}}

  config.before(:each, example_group: {:file_path => %r{spec/presenters}}) do
    setup_with_controller  # this is necessary because otherwise @controller is nil, but why?
  end
  ...
end

다른 팁

You can also create your own view:

let(:view) { ActionController::Base.new.view_context }
subject { OrderPresenter.new(order, view).subtotal }

https://www.ruby-forum.com/topic/2922913#1029887

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top