Matt Winckler
Matt Winckler

Reputation: 2233

Why is this RSpec test failing?

I'm in the process of learning Ruby on Rails, so treat me like a total neophyte, because I am.

I've got a User model with some associated RSpec tests, and the following test fails:

require 'spec_helper'
describe User do

    it 'should require a password' do
        User.new({:email => '[email protected]', :password => '', :password_confirmation => ''}).should_not be_valid
    end

end

The relevant part of the User model looks like this:

class User < ActiveRecord::Base
    ...
    validates :password, :presence => true,
                         :confirmation => true,
                         :length => { :minimum => 6 }
    ...
end

Here's the catch: if I run User.new(...).valid? from a Rails console using the arguments above, it returns false as expected and shows the correct errors (password is blank).

I was using spork/autotest and I restarted both to no avail, but this test also fails even running it directly with rspec. What am I doing wrong here?

EDIT

I tried a few more things with the test. This fails:

        u = User.new({:email => '[email protected]', :password => '', :password_confirmation => ''})
        u.should_not be_valid

So does this:

        u = User.new({:email => '[email protected]', :password => '', :password_confirmation => ''})
        u.valid?
        u.errors.should_not be_empty

This passes, confirming that :password is indeed blank:

        u = User.new({:email => '[email protected]', :password => '', :password_confirmation => ''})
        u.password.should == ''

Upvotes: 3

Views: 1424

Answers (2)

Spyros
Spyros

Reputation: 48696

So, it's actually spork that is causing the problem. You can turn caching off, so that it won't need restarting every time :

http://ablogaboutcode.com/2011/05/09/spork-testing-tip-caching-classes

I think this is what happens :

ruby-1.9.2-p180 :020 > u = User.new
 => #<User id: nil, email: ...
ruby-1.9.2-p180 :021 > u.errors
 => {} 
ruby-1.9.2-p180 :022 > u.save
 => false 
ruby-1.9.2-p180 :023 > u.errors
 => {:email=>["can't be blank", "can't be blank"], ...} 

In short, if you change new to create, it will work :) I think that this happens because the matcher be_valid checks on the model validation errors. There can be a deeper explanation, but i think that if you use create instead of new, it will work.

EDIT : I have a be_valid_verbose version that might help. Just create a 'be_valid_verbose.rb' file in your rspec/custom_matchers folder, and inside it write :

RSpec::Matchers.define :be_valid_verbose do
  match do |model|
    model.valid?
  end

  failure_message_for_should do |model|
    "#{model.class} expected to be valid but had errors:n #{model.errors.full_messages.join("n ")}"
  end

  failure_message_for_should_not do |model|
    "#{model.class} expected to have errors, but it did not"
  end

  description do
    "be valid"
  end
end

Now check against be_valid_verbose instead of be_valid. It will hopefully present you with some more information on what is happening in your case.

Upvotes: 2

Matt Winckler
Matt Winckler

Reputation: 2233

As I feared, the answer was stupidity. This was a spork problem. I thought I had killed the existing process and was running rspec independently, but I later found the spork process still running in a different shell, and rspec had been connecting to it all along. Restarting spork (or killing it entirely) and re-running the tests fixed the problem.

I found this particularly deceptive in that rspec continually updated the test output to reflect the fact that it was aware of my test changes, so it appeared to me that it was running against up-to-date code. Now I'm left to wonder what the real utility of spork is, since apparently I can't trust that it's actually running the right tests correctly.

Upvotes: 0

Related Questions