2010-12-01 93 views
1

我有一個嘲笑的問題。我有班級DistanceMatrix,我想 喜歡指出在if/else 語句中調用了form_matrix的哪個方法。我需要使用摩卡和RSpec。有任何想法嗎?紅寶石。嘲笑RSpec

​​

它試圖:

describe DistanceMatrix, "when mocking ..." do 
    it "should do call form_matrix" do 
    DistanceMatrix.any_instance.expects(:form_matrix).with([1]).once 
    DistanceMatrix.any_instance.expects(:get_data_from_yaml).with("file_name.yml").once.returns([1]) 
    DistanceMatrix.new("file_name.yml") 
    end 
end 

,但得到的錯誤:

Failures: 
    1) DistanceMatrix when mocking ... should do call form_matrix 
    Failure/Error: DistanceMatrix.new("file_name.yml") 
    unexpected invocation: #<AnyInstance:DistanceMatrix>.get_data_from_yaml('file_name.yml', nil) 
    unsatisfied expectations: 
    - expected exactly once, not yet invoked: #<AnyInstance:DistanceMatrix>.get_data_from_yaml('file_name.yml') 
    - expected exactly once, not yet invoked: #<AnyInstance:DistanceMatrix>.form_matrix([1]) 
    satisfied expectations: 
    - allowed any number of times, already invoked once: #<DistanceMatrix:0x9e48b40>.get_optimal_route(any_parameters) 
    - allowed any number of times, already invoked once: #<Database::Distances:0x9d59798>.load_distances(any_parameters) 
    # ./distance_matrix.rb:18:in `initialize' 
    # ./tsp_algorithm_spec.rb:253:in `new' 
    # ./tsp_algorithm_spec.rb:253:in `block (2 levels) in <top (required)>' 
Finished in 0.25979 seconds 

我發現,在我們的RSpec應該使用不.expects(),但.should_receive(),所以我嘗試:

describe DistanceMatrix, "when mocking ..." do 
    it "should do call form_matrix" do 
    DistanceMatrix.any_instance.should_receive(:form_matrix).with([1]) 
    DistanceMatrix.any_instance.should_receive(:get_data_from_yaml).with("file_name.yml").and_return([1]) 
    DistanceMatrix.new("file_name.yml") 
    end 
end 

但得到了新的失敗:

Failures: 
    1) DistanceMatrix when mocking ... should do call form_matrix 
    Failure/Error: DistanceMatrix.any_instance.should_receive(:form_matrix).with([1]) 
    (#<Mocha::ClassMethods::AnyInstance:0x96356b0>).form_matrix([1]) 
     expected: 1 time 
     received: 0 times 
    # ./tsp_algorithm_spec.rb:251:in `block (2 levels) in <top (required)>' 

Finished in 0.26741 seconds 
+0

#should_receive使用的RSpec的嘲弄 - 你原本說你用摩卡。如果你想使用摩卡,你應該在你的項目的spec_helper.rb中進行配置。 – karmajunkie 2010-12-01 20:16:34

+0

這兩個錯誤告訴你的是,form_matrix沒有按照你的預期調用。我認爲問題不在您的測試中。我的猜測是,你傳遞給初始化器的東西是一個包裝的字符串或者其他東西,所以args [0] .class!= String。你有沒有在調試器中逐步瞭解它是怎麼回事? – karmajunkie 2010-12-01 20:22:02

回答

0
DistanceMatrix.any_instance.expects(:form_matrix).with("String") # => supply the correct string param 

DistanceMatrix.any_instance.expects(:form_matrix).with([]) # => supply the correct array param 

我不知道你的get_data_from_db和get_data_from_yaml方法都在做,但你應該能夠控制這些輸入以及驗證正確的參數正在提供給form_matrix。

EDITED 你將不得不使用,而不是嘲諷的一個實例變量,因爲你想嘲笑在初始化的東西DistanceMatrix.any_instance。另外,如果模糊不清,您需要在設置上述行中的模擬後實際進行適當的方法調用,例如,

DistanceMatrix.new("SomeString") 

編輯

it "should do call #form_matrix with proper arguments" do 
    DistanceMatrix.any_instance.expects(:form_matrix).with([1]) 
    DistanceMatrix.any_instance.expects(:get_data_from_yaml).with("foo").returns([1]) 
    DistanceMatrix.new("foo") 
end 
3

我只有用摩卡,而不是RSpec的,但看着摩卡失敗消息的經驗,關鍵部件是這些: -

unexpected invocation: #<AnyInstance:DistanceMatrix>.get_data_from_yaml('file_name.yml', nil) 
unsatisfied expectations: 
- expected exactly once, not yet invoked: #<AnyInstance:DistanceMatrix>.get_data_from_yaml('file_name.yml') 

如果你看看這些行的結尾,你會注意到get_data_from_yaml沒有被調用期望的參數。正如預期的那樣,它被調用('filename.yml', nil)而不是('filename.yml')

這是因爲發生的事情,當你調用DistanceMatrix.new("file_name.yml")在您的測試,只有一個參數,然後裏面DistanceMatrix#initializeDistanceMatrix#get_data_from_yaml被稱爲與(args[0], args[1])以來args是一個單一的元素陣列,args[1]nil

也許這是你並不怎麼期待紅寶石工作,但下面演示了此行爲: -

def foo(*args) 
    puts "args[0]=#{args[0].inspect}; args[1]=#{args[1].inspect}" 
end 

foo("string") # => args[0]="string"; args[1]=nil