2010-04-30 9 views
9

La esencia de mi problema es el siguiente: -Cómo devolver un valor dinámico de un simulacro de Mocha en Ruby

Estoy escribiendo un simulacro de Mocha en Ruby para el método representado como "post_to_embassy" a continuación. No es realmente nuestra preocupación, con el propósito de describir el problema, lo que hace el método real. Pero necesito el simulacro para devolver un valor dinámico. El siguiente procedimiento '& prc' se está ejecutando correctamente en lugar del método real. Pero el método "con" en Mocha solo permite la devolución de valores booleanos. Por lo tanto, el siguiente código muestra cero. Necesito que muestre el valor que se pasa a través de orderInfoXml. ¿Alguien sabe de un método alternativo que puedo usar?

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") 

de salida: -

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

Respuesta

0

no he encontrado una manera de hacer la salida de un método burlado completamente dinámico, pero si usted tiene un número limitado, conocido de las entradas se puede obtener la salida para trabajar correctamente.

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) 

de salida:

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

Creo que esta respuesta es un poco engañoso. Aunque es correcto sugerir que puede usar Expectation # with para especificar diferentes valores de retorno para diferentes valores de parámetros, el uso de Procs no es necesario al especificar los valores de retorno. –

+0

Es cierto, el Proc no es necesario. Pude haber especificado los valores de retorno como cadenas, directamente. Usé un Proc en mi código de ejemplo para reflejar más de cerca la pregunta. – metavida

4

no estoy seguro de si hay un método perfecto para esto. Pero para hacer la vida más fácil, que para anular cada respuesta posible (como se describe en otra respuesta), se puede ir con el método yields de Mocha.

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 

salidas:

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

This is from the mocked proc:- 
foo 
foo 

Para ello será necesario asignar la devolución de su prc, y no es exactamente bastante (OMI). Pero no tienes que anular cada expectativa, lo que te dará un poco de libertad.

+3

Este no es el uso previsto de rendimientos de # expectativa. No recomendaría esta técnica. –

3

En general, normalmente es mejor que especifique valores de devolución explícitos en las pruebas. Tiende a hacer que las pruebas sean difíciles de entender y difíciles de mantener si introduce una lógica separada para determinar qué valor devolver.

Sugeriría que use Expectation#with con ParameterMatchers adecuado para definir explícitamente valores de retorno para diferentes valores de parámetros o use la funcionalidad StateMachine.

1

Mocha no parece ser compatible con esto. Agregue esto a su 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 

luego vuelva a colocar los últimos 4 líneas de su prueba con:

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) 
Cuestiones relacionadas