2010-12-01 3 views
1

У меня проблема с насмешкой. У меня есть класс DistanceMatrix, и я бы хотел бы указать, какой метод form_matrix был вызван в if/else . Мне нужно использовать мокко и RSpec. Есть идеи?Рубин. Смысл в RSpec

class DistanceMatrix 

def initialize(*args) 
    if args[0].class == String 
     form_matrix(get_data_from_yaml(args[0], args[1])) 
    elsif args[0].class == Array || args[0] == nil 
     form_matrix(get_data_from_db(args[0])) 
    end 
end 

def form_matrix(...) 
    ... 
end 

end 

он пытался:

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 в - вы изначально сказали, что вы использовали мокко. Если вы хотите использовать mocha, вы должны настроить это в 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") 

EDITED

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 
Смежные вопросы