2009-10-28 94 views
2

我一直無法找到任何此類情況。我定義它有一個名爲範圍的模型正是如此:在RSpec控制器中扼殺named_scope

class Customer < ActiveRecord::Base 
    # ... 
    named_scope :active_customers, :conditions => { :active => true } 
end 

和我試圖存根它在我的控制器規格:

# spec/customers_controller_spec.rb 
describe CustomersController do 
    before(:each) do 
    Customer.stub_chain(:active_customers).and_return(@customers = mock([Customer])) 
    end 

    it "should retrieve a list of all customers" do 
    get :index 
    response.should be_success 
    Customer.should_receive(:active_customers).and_return(@customers) 
    end 
end 

這不是工作和失敗,他說,客戶期望active_customers但收到0次。在我的實際控制人索引行動中,我有@customers = Customer.active_customers。我錯過了什麼讓這個工作?可悲的是,我發現編寫代碼比編寫測試/規範更容易,並且寫出來,因爲我知道規範描述的內容,而不是如何告訴RSpec我想做什麼。

回答

8

我認爲在stubsmessage expectations中存在一些混淆。消息預期基本上是存根,您可以在其中設置所需的預設響應,但它們也會測試正在測試的代碼所進行的調用。相比之下,存根就是對方法調用的罐頭響應。但不要在同一個方法和測試中混合一個存根與一個消息期望或不好的事情會發生 ...

回到你的問題,有兩件事(或更多?),需要spec'ing在這裏:

  1. 那CustomersController調用Customer#active_customers,當你做一個indexget。在本規範中返回Customer#active_customers並不重要。
  2. active_customers named_scope確實返回客戶,其中active字段爲true

我認爲你正在嘗試做數字1。如果是這樣,刪除整個存根和簡單地設置在您的測試消息的預期:

describe CustomersController do 
    it "should be successful and call Customer#active_customers" do 
    Customer.should_receive(:active_customers) 
    get :index 
    response.should be_success 
    end 
end 

在你沒有什麼測試上述規格它返回。這沒關係,因爲這是規範的目的(儘管你的規範太接近實現而不是行爲,但這是一個不同的話題)。如果您想撥打active_customers特別返回某些內容,請繼續並將.and_returns(@whatever)添加到該消息期望值中。故事的另一部分是測試active_customers如預期的那樣工作(即:實際調用數據庫的模型規範)。

Customer.stub_chain(:active_customers).and_return(@customers = [mock(Customer)]) 
+0

謝謝您的解釋(我在下面的一個RSpec教程,但是它是如何顯示到用模擬/存根執行操作)。然而,當我嘗試你發佈的代碼時,我得到了同樣的錯誤: expected:active_customers(任何參數)一次,但收到0次。儘管在CustomersController#index中調用了Customer.active_customers。 – 2009-10-28 19:57:55

+0

對不起,我的壞。對'get:index'的調用應該在消息期望之後。我正在糾正答案,以便期望成爲規範中的第一行。 – hgmnz 2009-10-28 20:45:32

+0

好的,現在正在工作。我習慣於正常的測試過程,get:index在測試之前出現,所以這似乎是問題。它與RSpec相反。我想我需要更多練習RSPec。謝謝! – 2009-10-29 12:50:11

1

,如果你想測試你接收回來的客戶記錄的數組,像這樣你應該有周圍的模擬陣列。

我有一個控制器調用

ExerciseLog.this_user(current_user).past.all 

而且我能夠存根,像這樣

ExerciseLog.stub_chain(:this_user,:past).and_return(@exercise_logs = [mock(ExerciseLog),mock(ExerciseLog)]) 
0

stub_chain已經工作最適合我:

+0

http://apidock.com/rspec/Spec/Mocks/Methods/stub_chain – jspooner 2010-05-28 16:25:07