15

私の問題の要点は次のとおりです。

以下の「post_to_embassy」で表されるメソッドの Mocha モックを Ruby で作成しています。問題を説明する目的で、実際のメソッドが何をするかは、私たちの関心事ではありません。しかし、動的な値を返すにはモックが必要です。以下の proc '&prc' は、実際のメソッドの代わりに正しく実行されています。しかし、Mocha の「with」メソッドでは、ブール値のみを返すことができます。したがって、以下のコードは nil を出力します。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

4 に答える 4

5

これに最適な方法があるかどうかはわかりません。しかし、(別の回答で説明されているように)考えられる各応答をスタブするよりも、生活を楽にするために、モカの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)。しかし、それぞれの期待を打ち消す必要はありません。これにより、かなりの自由が得られます。

于 2010-07-23T05:12:43.027 に答える
4

モカはこれをサポートしていないようです。これを 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)
于 2015-10-11T17:05:03.870 に答える
3

一般に、通常は、テストで明示的な戻り値を指定する方が適切です。返す値を決定するために別のロジックを導入すると、テストが理解しにくくなり、維持しにくくなる傾向があります。

適切なParameterMatchersで Expectation#withを使用して、さまざまなパラメーター値の戻り値を明示的に定義するか、StateMachine機能を使用することをお勧めします。

于 2010-09-26T16:43:45.153 に答える
0

モックされたメソッドの出力を完全に動的にする方法は見つかりませんでしたが、入力の数が限られている場合は、出力を正しく機能させることができます。

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."
于 2010-05-20T14:42:47.593 に答える