Testing a before_save callback with Rspec and Factory Girl
Asked Answered
C

1

7

I am pretty sure I am missing something really basic here.

I want to test if a before_save callback does what it is supposed to do, not just that it is called.

I wrote the following test:

it 'should add lecture to question_type' do      
  @course = Factory :course,
                    :start_time => Time.now - 1.hour,
                    :end_time => Time.now                        
  @question = Factory.create(:question, 
                             :course_id => @course.id, 
                             :created_at => Time.now - 10.minutes)                          
  @question.question_type.should == 'lecture'      
end

And I have the following factories for course and question:

Factory.define :course do |c|
  c.dept_code {"HIST"}
  c.course_code { Factory.next(:course_code) }
  c.start_time { Time.now - 1.hour }
  c.end_time { Time.now }
  c.lecture_days { ["Monday", Time.now.strftime('%A'), "Friday"]  }
end

Factory.define :question do |q|
  q.content {"Why don't I understand this class!?"}
  q.association :course
end

And I wrote the following callback in my Question model:

before_save :add_type_to_question

protected

def add_type_to_question
  @course = Course.find(self.course_id)
  now     = Time.now
  if (time_now > lecture_start_time && time_now < lecture_end_time ) && @course.lecture_days.map{|d| d.to_i}.include?(Time.now.wday)
    self.question_type = "lecture"
  end    
end

The test keeps failing saying that "got: nil" for question_type instead of 'lecture'

Since I didn't see anything obviously wrong with my implementation code, I tried the callback in my development environment and it actually worked adding 'lecture' to question_type.

This makes me think that there might be something wrong with my test. What am I missing here? Does Factory.create skip callbacks by default?

Chromoprotein answered 31/1, 2012 at 23:3 Comment(1)
Instead of before_save try before_validationColson
C
9

I would not use Factory.create to trigger the process. FactoryGirl should be used to create the test setup, not to trigger the actual code you want to test. Your test would then look like:

it 'should add lecture to question_type' do      
  course = Factory(:course, :start_time => Time.now - 1.hour, :end_time => Time.now)
  question = Factory.build(:question, :course_id => course.id, :created_at => Time.now - 10.minutes, :question_type => nil)

  question.save!                          
  question.reload.question_type.should == 'lecture'      
end

If this test still fails, you can start debugging:

Add a puts statement inside add_type_to_question and another one inside the if statement and see what happens.

Corcoran answered 31/12, 2012 at 13:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.