2012-08-07 38 views
3

試圖找出爲什麼我的rspec測試失敗。最值得注意的是似乎矛盾的失敗信息。說明我有一個ActiveRecord :: RecordInvalid錯誤,這正是我聲稱應該發生的事情。Rails Rspec模型規範用戶:email ActiveRecord :: RecordInvalid

這裏是我的user.rb

... 
validates_presence_of :email 
... 

這裏是我的users_spec.rb

... 
it "is invalid without email" do 
    Factory(:user, email: nil).should raise_error(ActiveRecord::RecordInvalid) 
end 
... 

這裏輸出:

Failures: 

    1) User a user (in general) is invalid without email 
    Failure/Error: Factory(:user, email: nil).should raise_error(ActiveRecord::RecordInvalid) 
    ActiveRecord::RecordInvalid: 
     Validation failed: Email is invalid, Email can't be blank 
    # ./spec/models/user_spec.rb:34:in `block (3 levels) in <top (required)>' 

本來我是這樣的測試,但它保持失敗,所以我決定指定我期待的錯誤。

it "is invalid without email" do 
    Factory(:user, email: nil).should_not be_valid 
end 

回答

8

你的代碼是不工作的原因是你想實際測試其有效性之前創建一個無效的模型。你想要做的是建立一個有效的模式,改變的東西,並檢查它是無效的,就像這樣:

it "is invalid without email" do 
    user = Factory(:user) 
    user.email = nil 
    user.should_not be_valid 
end 

我個人很喜歡來定義我的模型在before塊,設置是爲subject,然後更改屬性中的每個規格和檢查的有效性,這樣的:

before do 
    @user = FactoryGirl.create(:user) 
end 

subject { @user } 

it "is invalid without email" do 
    subject.email = nil 
    should_not be_valid 
end 

爲了記錄在案,如果你想測試記錄創建引發的錯誤(這絕對是做到這一點的最好方式) ,你可以通過將Factory呼叫打包在lambda,像這樣:

lambda { 
    Factory(:user, :email => nil) 
}.should raise_error(ActiveRecord::RecordInvalid) 
+0

謝謝,這完全有道理。你覺得讓(!:user){Factory(:user)}而不是之前做...結束? – botbot 2012-08-07 22:34:57

+0

順便說一句,爲什麼你不建議*不*包裝在一個lambda {}或期待{}? – botbot 2012-08-07 22:41:24

+0

我的意思是我不會建議通過檢查錯誤提示來檢查有效性。使用'lambda'來檢查在其他上下文中引發錯誤是完全正確的。 – 2012-08-07 22:47:40