Как вернуть динамическое значение из макета Mocha в Ruby - PullRequest
12 голосов
/ 30 апреля 2010

Суть моей проблемы заключается в следующем: -

Я пишу макет Mocha на Ruby для метода, представленного ниже как "post_to_embassy". На самом деле, с целью описания проблемы мы не заботимся о том, что делает настоящий метод. Но мне нужно макет, чтобы вернуть динамическое значение. Процедура '& prc' ниже правильно выполняется вместо фактического метода. Но метод «с» в Mocha позволяет возвращать только логические значения. Таким образом, код ниже выводит ноль. Мне нужно, чтобы вывести значение, передаваемое через orderInfoXml. Кто-нибудь знает альтернативный метод, который я могу использовать?

require 'rubygems'
require 'mocha'
include Mocha::API

class EmbassyInterface 
  def post_to_embassy(xml)
    puts "This is from the original class:-"
    puts xml
    return xml
  end
end

orderInfoXml = "I am THE XML"

mock = EmbassyInterface.new
prc = Proc.new do |orderXml| 
  puts "This is from the mocked proc:-"
  puts orderXml
  orderXml
end

mock.stubs(:post_to_embassy).with(&prc)
mock_result = mock.post_to_embassy(orderInfoXml)
p mock_result
#p prc.call("asd")

Выход: -

This is from the mocked proc:-
I am THE XML
nil

Ответы [ 4 ]

5 голосов
/ 23 июля 2010

Я не уверен, есть ли идеальный метод для этого. Но чтобы упростить жизнь, а не заглушать каждый возможный ответ (как описано в другом ответе), вы можете использовать метод Мокко yields.

require "rubygems"
require "mocha"

include Mocha::API

class EmbassyInterface

  def post_to_embassy(xml)
    puts "This is form the original class:-"
    puts xml
    xml
  end
end

order_info_xml = "I am the xml"

mock = EmbassyInterface.new

prc = Proc.new do |order_xml|
  puts "This is from the mocked proc:-"
  puts order_xml
  order_xml
end

mock.stubs(:post_to_embassy).yields prc

prc_return = nil

mock.post_to_embassy { |value| prc_return = value.call("hello world") }
puts prc_return

mock.post_to_embassy { |value| prc_return = value.call("foo") }
puts prc_return

выходы:

This is from the mocked proc:-
hello world
hello world

This is from the mocked proc:-
foo
foo

Это потребует от вас назначить возврат вашего prc, и это не совсем красиво (imo). Но вам не нужно заглушать каждое ожидание, что даст вам немного свободы.

3 голосов
/ 26 сентября 2010

Как правило, вам лучше указывать явные возвращаемые значения в тестах. Это делает тесты трудными для понимания и сложными для обслуживания, если вы вводите отдельную логику для определения возвращаемого значения.

Я бы посоветовал вам либо использовать Expectation # с с подходящими ParameterMatchers для явного определения возвращаемых значений для различных значений параметров, либо использовать функциональность StateMachine .

2 голосов
/ 11 октября 2015

Мокко, кажется, не поддерживает это. Добавьте это в свой test_helper.rb:

# Replace klass's method_name with method_implementation
def stub_replace(klass, method_name, &method_implementation)
  klass.singleton_class.send(:alias_method, "#{method_name}_mock_backup", method_name)
  klass.define_singleton_method(method_name, method_implementation)
end

def undo_stub_replace(klass, method_name)
  klass.singleton_class.send(:alias_method, method_name, "#{method_name}_mock_backup")
end

Затем замените последние 4 строки вашего теста на:

stub_replace(EmbassyInterface, :post_to_embassy, &prc)
mock_result = mock.post_to_embassy(orderInfoXml)
p mock_result

# cleanup
undo_stub_replace(EmbassyInterface, :post_to_embassy)
0 голосов
/ 20 мая 2010

Я не нашел способа сделать вывод моделируемого метода полностью динамическим, но если у вас ограниченное, известное количество входов, вы можете заставить вывод работать правильно.

require 'rubygems'
require 'mocha'
include Mocha::API

class EmbassyInterface 
  def post_to_embassy(xml)
    "original: #{xml}"
  end
end

to_mock = EmbassyInterface.new
orderInfoXml1 = "I am the first XML."
orderInfoXml2 = "I am the second XML."

p to_mock.post_to_embassy(orderInfoXml1)

prc = Proc.new do |xml| 
  "mocked: #{xml}"
end
to_mock.stubs(:post_to_embassy).with(orderInfoXml1).returns(prc.call(orderInfoXml1))
to_mock.stubs(:post_to_embassy).with(orderInfoXml2).returns(prc.call(orderInfoXml2))

p to_mock.post_to_embassy(orderInfoXml1)
p to_mock.post_to_embassy(orderInfoXml2)
p to_mock.post_to_embassy(orderInfoXml1)

выход:

"original: I am the first XML."
"mocked: I am the first XML."
"mocked: I am the second XML."
"mocked: I am the first XML."
...