2010-12-01 67 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