Reputation: 2233
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
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
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