2017-10-04 61 views
0

我有我的控制器,從一個API我無法控制加載了一個對象的實例的實例變量的作用:Ruby on Rails的:硒覆蓋實例變量測試

def index 
    @obj = MyObj.find(id: params[:id]) 
end 

MyObj中。找到一個API調用並返回該API返回的內容。

現在說我想爲我的視圖編寫一個測試,但我無法使用測試數據庫,因爲我的應用程序依賴於該API。我永遠無法指望API返回一個可測試對象,我想嘗試的一些測試依賴於該對象的狀態。

我希望能夠在呈現我的視圖之前,手動創建我自己的測試@obj,並讓我的測試對該視圖呈現工作在@obj通知的視圖渲染上。

理想情況下是這樣的:

before(:all) do 
    @obj = {attr1: "abc", attr2: 123} 
    driver.navigate.to("#{ENV['RAILS_HOST']}/my_view/123") 
end 

其中明確不起作用。有沒有辦法做到這一點?

編輯:試圖存根方法似乎沒有工作,這裏是它目前的樣子:

規格:

before(:each) do 
    allow(Library::Equipment) 
    .to receive(:mymethod) 
    .with(123) 
    .and_return("Stub method") 

    puts Library::Equipment.mymethod(123) 
    #prints "Stub method" 
    driver.navigate.to("#{ENV['RAILS_HOST']}/library/equipments/123/variables") 
end 

/library/equipments/:equipment_id/variables路線library/variables#index,它看起來像這樣:

def index 
    @test = Library::Equipment.mymethod(123) 
    puts @test 
    #prints "Real method" 
    # other code... 
end 

我的Library::Equipment班有這樣的班級方法:

def self.mymethod(param) 
    "Real method" 
end 

而在我的index.html.erb中,我只需要<%= @test %>即可查看它包含的內容。正如你所看到的,mymethod回報有所不同,當從我的規範文件,並從我的index行動稱爲

+0

使用'RSpec :: Mocks.with_temporary_scope'將允許您在'before(all)'中使用存根,但當範圍結束時將刪除存根。請刪除'with_temporary_scope',並在同一時間之前將(:all)'前面的(:each)'/'前面的''改成''。 – ulferts

+0

結果是一樣的,我編輯了問題以反映所做的更改。 – bpromas

回答

1

您可以通過rspec's allow方法存根調用MyObj.find

let(:obj) { { attr1: "abc", attr2: 123 } } 
let(:obj_id) { 123 } 

before(:each) do 
    allow(MyObj) 
    .to receive(:find) 
    .with(id: obj_id) 
    .and_return(obj) 

    driver.navigate.to("#{ENV['RAILS_HOST']}/my_view/123") 
end 

allow會爲您提供的可能性,模擬對方法調用的響應(例如find)並返回您選擇的答案。這樣,當你的控制器打電話給MyObj.find時,find的實際實現不被調用,而是rspec代碼,它返回通過and_return指定的對象。 with方法僅用於縮小模擬範圍,以便模擬參數不匹配時不會響應。你的情況可能是可選的。

請注意,我將before(:all)更改爲before(:each)。前者只會在整個套件之前執行一次。由於您需要進行獨立測試,因此您不希望改變obj,這會影響下一次測試。此外,看起來不可能在before(:all)區塊中訪問let

鑑於硒測試通常是驗收測試,但是我會發現這樣的嘲諷可疑。

如果您無法訪問外部API,則提供canned responses可能會令人惱怒,但至少需要清除被殘留的圖層。

+0

我無法讓它工作。我收到了有關「在'before(:context)'鉤子」中訪問let聲明obj_id的錯誤。另外,這個「允許」方法究竟是如何工作的?這是否意味着我每次調用MyObj.find(id:123)時都會返回該特定對象?這在我的控制器內工作? – bpromas

+1

@bpromas我闡述了回答你的問題的答案。 – ulferts

+0

這不起作用。在我的控制器動作中運行的'find'(由於我的'driver.navigate.to'調用)運行正常,未能找到id = 123的東西。但是,如果我調用MyObj.find(id:123)在'allow'方法下,它返回給我'{attr1:「abc」,attr2:123}',它應該是這樣。兩個問題:1)MyObj在這裏意味着一個類,對嗎? 2)在我的情況下,MyObj沒有'find'方法,但包含支持模型中的一個。這是否改變了事情? – bpromas