[rspec-users] Unexpected before :each behavior.

Andrew Kasper andrew.m.kasper at gmail.com
Mon Dec 6 21:12:14 EST 2010


Hi gang.

I've come across what I believe to be unexpected behavior for some of my
before :each blocks, and I wonder if anyone can enlighten me as to why this
is happening.

The surprising thing happens when I run a 'before :each' inside of an each
block on a Hash. I have a #before_save hook in my ActiveRecord model. When I
call @sample_model.save from the before block, the model runs a uniqueness
validation. However, when I save from within the example, the save works
fine.

Below is the minimal test case I was able to put together:

class SampleClassMigration < ActiveRecord::Migration
  def self.up
    create_table :sample_classes do |t|
      t.string :sample_field
      t.string :attrib_1
      t.string :attrib_2
    end
  end
end

class SampleClass < ActiveRecord::Base
  validates_uniqueness_of :sample_field
  before_save :prep
  def prep
    self.sample_field = 'sample_value'
  end
end

describe SampleClass do
  EXAMPLES = {
    :attrib_1 => 'foo',
    :attrib_2 => 'bar'
  }
  EXAMPLES.each do |key, value|
    before(:each) do
      @sample = SampleClass.new(key => value)
      #In the passing case, this call to #save
      #is moved into the 'it' block
      @sample.save
    end

    it "key : #{value}\tvalue : #{key.to_s}" do
      #in the other case, I call the spec here
      @sample.should be_valid
    end
  end
end

It was my expectation that calling an instance method in the before block
would be the same as calling it within the example block. Instead, I get two
different results. When called from within the it block, both examples pass.
When called from within the before block, they both fail:

1)
'SampleClass key : bar  value : attrib_2' FAILED
Expected #<SampleClass id: 2, sample_field: "sample_value", attrib_1: "foo",
attrib_2: nil> to be valid, but it was not
Errors: Sample field has already been taken
./spec/models/minimal_spec.rb:20:

2)
'SampleClass key : foo  value : attrib_1' FAILED
Expected #<SampleClass id: 2, sample_field: "sample_value", attrib_1: "foo",
attrib_2: nil> to be valid, but it was not
Errors: Sample field has already been taken
./spec/models/minimal_spec.rb:20:

I'm surprised to see that the example fails, but I'm more surprised to see
that it fails both times. It is apparently the case that the "before" block
is executed on every iteration of the "each" block (but that the examples
themselves are executed later).

1) Is this a bug?
2) Is it a known behavior?
3) Is there a "BDD-theoretical" better way to do something like this
(assuming a larger hash of examples, for instance)?

I'm using:

gem 'rails',       '2.3.5'
gem 'mysql'
group :development, :test do
  gem 'database_cleaner'
  gem 'rspec-rails', '1.3.2'
  gem 'rspec', '1.3.0'
end

DatabaseCleaner is properly configured, and runs for many other specs.
(Indeed, it even runs correctly between steps, as demonstrated by the case
where the specs pass).

Thanks,
Andrew Kasper
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20101206/ee29008a/attachment-0001.html>


More information about the rspec-users mailing list