2017-04-27 95 views
-2

我如何可以模擬調用函數說法,我與RSpec的測試 我做這樣的:RSpec的模擬調用函數的參數

module Module1 
    def find_item(str, item_class) 
    arr = item_class.find_or_initialize_by(...) 
    end 
end 

然後在規格:

let!(:dummy_class) { Class.new { extend Module1 } } 

it 'calls find_or_initialize_by' do 
    item_class = double("Item") 
    allow(dummy_class).to receive(:item_class).and_return(item_class) 
    expect(item_class).to receive(:find_or_initialize_by) 
    dummy_class.find_item("item1", Item) 
end 

它提出了一個錯誤「#不執行:item_class」 我試圖使用class_double和instance_double,但它是無益的。

Failures:

1) Module1#find_items Failure/Error: allow(dummy_class).to receive(:item_class) # does not implement: item_class # ./spec/..._spec.rb:26:in `block (3 levels) in '

26行:允許(dummy_class)。爲了接收(:item_class).and_return(item_class)

+0

你好,你能否添加更多信息你得到的錯誤? – Bohdan

+0

我更新了我的帖子 – andgursky

+0

http://stackoverflow.com/help/accepted-answer – engineersmnky

回答

1

不知道爲什麼你要這樣理解,但你是不是太遙遠。

目前,你要使用

allow(dummy_class).to receive(:item_class).and_return(item_class) 

item_class是不是隻是一個local_variable的方法。

Message Allowance語法簡而言之就是allow(object).to receive(method_name).with(arguments).and_return(return_value)

Message Expectation語法是expect(object).to receive(method_name).with(arguments).and_return(return_value)

因此,也許你的意思是allow(dummy_class).to receive(:find_item).with(item_class).and_return(item_class)因爲find_item是方法實際上是被稱爲和item_class傳入的說法,但因爲你是剔除返回值,那麼方法的主體永遠不會發生。

進一步你可以allow(dummy_class).to recieve(:find_item).and_call_original但這並不是真正的目的,因爲dummy_class是不是一個雙重的,並已被允許調用其原始版本find_item

因此,讓我們使用dummy_classallow(item_class).to receive(:find_or_initialize_by)的本機功能,然後下面的工作。

it 'calls find_or_initialize_by' do 
    item_class = double("Item") 
    allow(item_class).to recieve(:find_or_initialize_by) #needed because it is a test double and knows nothing 
    expect(item_class).to receive(:find_or_initialize_by) 
    dummy_class.find_item("item1", item_class) #used test double here to trap messages 
end 

替代地,我們可以使用的Item部分雙鍵和跳過Test Doubleitem_class例如

#please note this binds the test to Item existing 
it 'calls find_or_initialize_by' do 
    allow(Item).to receive(:find_or_initialize_by) #now a stubbed method on a partial double(Item) 
    expect(Item).to receive(:find_or_initialize_by) 
    dummy_class.find_item("item1", Item) #used the partial double 
end 

Partial doubles是好的,因爲它們可以驗證雙打和將確保Object實際上定義磕碰之前該方法。

如此說來給你測試的性質和事實dummy_class是不是雙(因此沒有必要allow任何東西),你是不會測試任何返回值就按這個,我只想用Spy,因爲他們建議只是爲了消息的期望。 它使測試更簡單,更清晰,無任何依賴關係:

it 'calls find_or_initialize_by' do 
    item = spy("item") 
    dummy_class.find_item("item1", item) 
    expect(item).to have_received(:find_or_initialize_by) 
end 

他們有部分雙味太但這是依賴於Item被已知並加載Object:(非常類似於以上,但預期是一種

#please note this binds the test to Item existing 
it 'calls find_or_initialize_by' do 
    allow(Item).to receive(:find_or_initialize_by) 
    dummy_class.find_item("item1", Item) 
    expect(Item).to have_received(:find_or_initialize_by) 
end 

另外讓通話效果)後,我們假設在Module1(...)看起來像name: str那麼我會建議測試,以及它被稱爲以正確的參數如

it 'calls find_or_initialize_by with args' do 
    item = spy("item") 
    dummy_class.find_item("item1", item) 
    expect(item).to have_received(:find_or_initialize_by).with(name: 'item1') 
end 

這可以確保不僅可以進行呼叫,而且可以將預期的參數傳遞給呼叫。

特別是隨着消息的預期的Module測試中,我會盡量保持測試雙打和間諜,因爲它使獨立和快速測試(當Item不再存在,會發生什麼?)

相關問題