3

I have an Active Record based model:- House

It has various attributes, but no formal_name attribute. However it does have a method for formal_name, i.e.

def formal_name
    "Formal #{self.other_model.name}"
end

How can I test that this method exists?

I have:

describe "check the name " do

    @report_set = FactoryGirl.create :report_set
    subject  { @report_set }
    its(:formal_name) { should == "this_should_fail"  }
end

But I get undefined method 'formal_name' for nil:NilClass

Michael Durrant
  • 93,410
  • 97
  • 333
  • 497
  • 1
    The problem isn't that formal_name isn't there, the problem is that your `@report_set` is `nil`. Try putting the create logic in a `let {}` block – DVG Jul 12 '12 at 16:52

2 Answers2

3

First you probably want to make sure your factory is doing a good job creating report_set -- Maybe put factory_girl under both development and test group in your Gemfile, fire up irb to make sure that FactoryGirl.create :report_set does not return nil.

Then try

describe "#formal_name" do
  let(:report_set) { FactoryGirl.create :report_set }

  it 'responses to formal_name' do
    report_set.should respond_to(:formal_name)
  end

  it 'checks the name' do
    report_set.formal_name.should == 'whatever it should be'
  end
end
Wei
  • 1,252
  • 13
  • 19
  • I wouldn't do the `respond_to` test. At that point you're testing ruby and that's not necessary. But to be fair the author did ask about it. – Dty Jul 12 '12 at 17:07
  • This is the very first I ever wrote a respond_to test TBH. I only wrote it because @michael-durrant asked for it. =P I agree that his problem is most likely not with the respondence of the method but rather with his factory setup and/or definition. – Wei Jul 12 '12 at 17:15
  • the respond_to is the only part that works. I made sure that respond_to(:junk) didn't work and that respond_to(:name) did work. The simple test for checking of the value I couldn't get to work using this or any other format. – Michael Durrant Jul 12 '12 at 18:48
1

Personally, I'm not a fan of the shortcut rspec syntax you're using. I would do it like this

describe '#formal_name' do
  it 'responds to formal_name' do
    report_set = FactoryGirl.create :report_set
    report_set.formal_name.should == 'formal_name'
  end
end

I think it's much easier to understand this way.


EDIT: Full working example with FactoryGirl 2.5 in a Rails 3.2 project. This is tested code
# model - make sure migration is run so it's in your database
class Video < ActiveRecord::Base
  # virtual attribute - no table in db corresponding to this
  def embed_url
    'embedded'
  end
end

# factory
FactoryGirl.define do
  factory :video do
  end
end

# rspec
require 'spec_helper'

describe Video do
  describe '#embed_url' do
    it 'responds' do
      v = FactoryGirl.create(:video)
      v.embed_url.should == 'embedded'
    end
  end
end

$ rspec spec/models/video_spec.rb  # -> passing test
Dty
  • 12,253
  • 6
  • 43
  • 61
  • -1 works for ID (a real attribute) but not for name (a virtual attribute). I get undefined method 'name' – Michael Durrant Jul 12 '12 at 18:41
  • @MichaelDurrant I'm using factory girl 2.5 and factory girl rails 1.6 and it definitely works with virtual attributes. Not sure why it's not working for you. I'm adding a full example with tested code – Dty Jul 12 '12 at 23:44