2014-02-09 98 views
0

我正在構建一個非常小的Sinatra API,今天我開始爲它編寫測試。我正在使用RSpec和FactoryGirl。RSpec不應該失敗。爲什麼?

我有一個用戶模型,在控制器中我檢查註冊的用戶的電子郵件是否已經保存。如果保存,則返回402,否則我創建用戶並返回200.爲了測試此操作,我使用相同的參數對users路由執行POST兩次,第一次檢查last_response.should be_ok,因爲DB是空,所以我可以創建用戶,然後我有另一個測試,POST到users路由與以前相同的參數,但期待last_response.should_not be_ok,我得到一個200!所以測試失敗!

這是我的末日路線:

post '/users' do 
    user = User.where(email: params[:email]).first 

    if !user 
     user = User.create(email: params[:username], password_not_hashed: params[:password]) 
     halt 200, {user:user}.to_json 
    end 

    halt 409, {error:"user already exists"}.to_json 
end 

這是我的測試:

describe 'Create User' do 
    include Rack::Test::Methods 
    params = {} 
    params['password'] = "username" 
    params['username'] = "[email protected]" 

    it "should create a user" do 
     post '/users', params 
     last_response.should be_ok 
    end 

    it "should fail to create a user because its duplicate user" do 
     post '/users', params 
     last_response.should_not be_ok 
    end 
end 

而且我得到一個失敗,因爲上次測試的響應是200我已經打印paramslast_responsepp這是我得到了什麼:

PARAMS:

{"password"=>"username", "username"=>"[email protected]"} 

last_response

@block=nil, 
@body=["{\"user\":{\"id\":null,\"email\":\"[email protected]\"}}"], 
@body_string=nil, 
@chunked=false, 
@errors="", 
@header= 
    {"Content-Type"=>"text/html;charset=utf-8", 
    "Content-Length"=>"52", 
    "X-XSS-Protection"=>"1; mode=block", 
    "X-Content-Type-Options"=>"nosniff", 
    "X-Frame-Options"=>"SAMEORIGIN"}, 
    @length=52, 
    @original_headers= 
    {"Content-Type"=>"text/html;charset=utf-8", 
     "Content-Length"=>"52", 
     "X-XSS-Protection"=>"1; mode=block", 
     "X-Content-Type-Options"=>"nosniff", 
     "X-Frame-Options"=>"SAMEORIGIN"}, 
    @status=200, 

任何想法?!?!這讓我瘋狂!

編輯:

剛剛添加了一個活動記錄驗證(validates_uniqueness_of :email),並在我的測試的輸出我得到如下:

Failure/Error: post '/users', params 
ActiveRecord::RecordInvalid: 
Validation failed: Email has already been taken 

所以,這意味着有與已建立的用戶該電子郵件,所以我仍不明白爲什麼測試失敗,並且創建用戶的路線總是進入if !user

以下是代碼覆蓋率的輸出: enter image description here

瘋了......我很迷茫!

編輯:

另外我有一個after all rspec的鉤但不應該被importat因爲這一切都在測試後才能運行:

after :all do 
    ActiveRecord::Base.subclasses.each(&:delete_all) 
end 
+0

如何在第14行更改條件?我一直在玩irb的用戶條件,我想知道它是否一直評估我們期望的方式。我仍然不確定。使用「if user.nil?」怎麼樣?代替?這似乎更精確一點。 –

+0

同樣的問題...將其更改爲user.nil?並仍在進入! – Andres

+0

添加打印語句或斷點時發生了什麼?您是否可以在測試執行期間檢查數據庫的狀態? –

回答

2

感謝您的詳細具體的問題 - 這是真的很好地放在一起。我懷疑你之前給/ user的帖子在測試之間沒有在你的測試數據庫中保存新用戶。您是否嘗試過在第二次調用中輸入print語句以確保您的測試數據庫包含用戶?這看起來像這樣:

it "should fail to create a user because its duplicate user" do 
    puts User.where(email: params[:email]).first 
    post '/users', params 
    last_response.should_not be_ok 
end 

您可能還想安裝pry並在測試中放置一個斷點。您可以在這裏閱讀更多關於pry:https://github.com/pry/pry。這可以讓你在代碼執行時檢查你的測試數據庫的狀態。一旦安裝了撬,你可以一個互動的休息添加到您的代碼是這樣的:

require 'pry' 

<other test business happens> 


it "should fail to create a user because its duplicate user" do 
    binding.pry 
    post '/users', params 
    last_response.should_not be_ok 
end 

如果你的測試數據庫確實不保留職位,以/用戶之間的數據,你可以嘗試這樣的事情對於你的第二個測試在嘗試發帖前添加用戶:

it "should fail to create a user because its duplicate user" do 
    User.create(email: params[:username], password_not_hashed: params[:password]) 
    post '/users', params 
    last_response.should_not be_ok 
end 
+0

感謝您的回答!我添加了唯一性的活動記錄驗證,並且出現活動記錄錯誤,所以發生了一些奇怪的事情......用戶在第一次調用時創建,但我不知道爲什麼在數據庫的第二次調用中找不到它... 奇怪的 – Andres

相關問題