Рубин. Издеваться в RSpec - PullRequest
       16

Рубин. Издеваться в RSpec

1 голос
/ 01 декабря 2010

У меня проблема с издевательством. У меня есть класс DistanceMatrix, и я бы хотел бы указать, какой метод form_matrix был вызван в if / else заявление. Мне нужно использовать мокко и 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 мы должны использовать не .expected (), а .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

Ответы [ 2 ]

3 голосов
/ 04 декабря 2010

У меня есть только опыт использования Mocha, а не RSpec, но, глядя на сообщение о сбое Mocha, ключевые части таковы: -

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#initialize DistanceMatrix#get_data_from_yaml вызывается с (args[0], args[1]), и поскольку args является массивом из одного элемента, args[1] будет nil.

Возможно, это не то, как вы ожидали, что Ruby будет работать, носледующее демонстрирует это поведение: -

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

foo("string") # => args[0]="string"; args[1]=nil
0 голосов
/ 01 декабря 2010
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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...