[rspec-users] Problem with view spec - works inside the browser but spec fails with nil object

Caio Moritz Ronchi caiomoritz at gmail.com
Sun Nov 11 20:10:40 EST 2007


Hi Hans,

I rewrote my specs the way you suggested and now everything works!

For those who are interested, here's how the code looks like now (after
following Hans' tips).

> a) writing a separate spec for the partial _question_for_candidate

require File.dirname(__FILE__) + '/../../spec_helper'

module QuestionForCandidatePartialHelper
  def get_question_type_mock(type)
    mock_model(QuestionType, {:name => type})
  end

  def render_question_for_candidate_partial
    render(:partial => 'survey/question_for_candidate', :locals =>
{:question => @question})
  end
end

describe 'partial survey/_question_for_candidate.rhtml' do
  include QuestionForCandidatePartialHelper

  before(:each) do
    @question = mock_model(Question, {
      :id => 1,
      :description => 'The description',
      :position => 4,
      :alternatives => [mock_model(Alternative, {:id => 1, :description =>
'Alternative 1 Description'})],
    })
    @question_type_exclusive = get_question_type_mock('exclusive')
    @question_type_multiple = get_question_type_mock('multiple')
  end

  it 'should render the top of the template no matter the question type' do
    @question.stub!(:question_type).and_return(@question_type_exclusive)
    render_question_for_candidate_partial
    response.should have_tag('div.question.question-4') do
      with_tag('.heading .number', '4.')
      with_tag('.heading .description', @question.description)
    end
  end

  it 'should render an exclusive-answer question' do
    @question.stub!(:question_type).and_return(@question_type_exclusive)
    render_question_for_candidate_partial
    response.should have_tag('div.question.question-4') do
      with_tag('input[type=?]', 'radio')
      without_tag('input[type=?]', 'checkbox')
    end
  end

  it 'should render a multiple-answer question' do
    @question.stub!(:question_type).and_return(@question_type_multiple)
    render_question_for_candidate_partial
    response.should have_tag('div.question.question-4') do
      with_tag('input[type=?]', 'checkbox')
      without_tag('input[type=?]', 'radio')
    end
  end
end

> b) write a separate spec for the helper that renders the question

require File.dirname(__FILE__) + '/../spec_helper'

describe SurveyHelper do
  before(:each) do
    @question = mock_model(Question)
  end

  it 'should render a question using the question_for_candidate partial' do
    self.should_receive(:render).with(:partial => 'question_for_candidate',
:locals => {:question => @question})
    render_question(@question)
  end
end

> b) in the view spec for /survey/show use should_receive to determine
that the helper is actually being called

require File.dirname(__FILE__) + '/../../spec_helper'

describe '/survey/show' do
  before(:each) do
    assigns[:configurations] = {:survey_name => 'Whatever'}
    @positions = [4, (9..22).to_a].flatten
    @questions = Array.new
    @positions.each do |position|
      @questions[position] = mock_model(Question, {
        :id => 1,
        :description => 'The description',
        :position => 4,
        :alternatives => [mock_model(Alternative, {:id => 1, :description =>
'Description'})],
        :question_type => mock_model(QuestionType, {:name => 'exclusive'})
      })
    end
    assigns[:questions] = @questions
  end

  it "should render the 'survey/question_for_candidate' partial" do
    args = {:partial => 'question_for_candidate', :locals => {:question =>
an_instance_of(Question)}}
    template.should_receive(:render).with(args).exactly(@questions.nitems
).times
    render 'survey/show'
  end
end

c) not use any fixtures in the view specs but instead use mocks for
that: it's faster and you can check exactly what needs to happen instead
of relying on what happens to be in the fixture.

As you can see mocks are now all over the place. No fixtures were used ;)

Thanks a lot,

Caio

On Nov 11, 2007 6:01 AM, Hans de Graaff <hans at degraaff.org> wrote:

> You are trying to test a lot of things at the same time, which is one of
> the reasons that it is now hard to diagnose a problem.
>
> I would tackle this by
> a) writing a separate spec for the partial _question_for_candidate
> b) write a separate spec for the helper that renders the question
> b) in the view spec for /survey/show use should_receive to determine
> that the helper is actually being called
> c) not use any fixtures in the view specs but instead use mocks for
> that: it's faster and you can check exactly what needs to happen instead
> of relying on what happens to be in the fixture.
>
> I'm afraid that I don't see immediately why your current setup won't
> work, but untangling things along the lines sketched above should
> hopefully get you to a situation where it becomes easier to see what
> happens.
>
> >   before(:each) do
> >     assigns[:configurations] = {:survey_name => 'Whatever'}
> >     assigns[:questions] = Array.new
> >     assigns[:questions][4] = questions(:faixa_etaria)
>
> I am a little bit suspicious about this construction, though. I'm not
> sure whether assigns is a normal Array in this case, so I'd create the
> Array and populate it before handing it to assigns:
>
> @questions = Array.new
> @questions[4] = ...
> assigns[:questions] = @questions
>
> Kind regards,
>
> Hans
>
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>



-- 
Caio Moritz Ronchi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://rubyforge.org/pipermail/rspec-users/attachments/20071111/caa9da66/attachment.html 


More information about the rspec-users mailing list