2010-04-30 3 views
9

L'essentiel de mon problème est le suivant: -Comment retourner une valeur dynamique à partir d'une maquette Mocha en Ruby

J'écris une maquette Mocha en Ruby pour la méthode représentée comme « post_to_embassy » ci-dessous. Ce n'est pas vraiment notre préoccupation, dans le but de décrire le problème, ce que la méthode actuelle fait. Mais j'ai besoin du simulacre pour retourner une valeur dynamique. Le processus '& prc' ci-dessous s'exécute correctement à la place de la méthode actuelle. Mais la méthode "with" dans Mocha permet uniquement de renvoyer des valeurs booléennes. Donc, le code ci-dessous produit zéro. J'en ai besoin pour afficher la valeur transmise par orderInfoXml. Est-ce que quelqu'un sait d'une autre méthode que je peux utiliser?

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

sortie: -

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

Répondre

0

Je n'ai pas trouvé un moyen de rendre la sortie d'une méthode complètement moqué dynamique, mais si vous avez un certain nombre, connu limité d'entrées, vous pouvez obtenir la sortie pour fonctionner correctement.

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) 

sortie:

"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

Je pense que cette réponse est un peu trompeur. Bien qu'il soit correct de suggérer que vous pouvez utiliser Expectation # avec pour spécifier des valeurs de retour différentes pour différentes valeurs de paramètre, l'utilisation de Procs n'est pas nécessaire pour spécifier les valeurs de retour. –

+0

True, le Proc n'est pas nécessaire. J'aurais pu spécifier les valeurs de retour sous forme de chaînes, directement. J'ai utilisé un Proc dans mon exemple de code pour refléter plus fidèlement la question. – metavida

4

Je ne sais pas s'il existe une méthode parfaite pour cela. Mais pour faciliter la vie, plutôt que de céder chaque réponse possible (comme décrit dans une autre réponse), vous pouvez utiliser la méthode 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 

sorties:

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

This is from the mocked proc:- 
foo 
foo 

Cela vous obligera à affecter le rendement de votre prc, et ce n'est pas exactement assez (imo). Mais, vous n'avez pas à dépasser chaque attente, ce qui vous donnera un peu de liberté.

+3

Ce n'est pas l'utilisation prévue des rendements # d'attente. Je ne recommanderais pas cette technique. –

3

En général, il est généralement préférable de spécifier des valeurs de retour explicites dans les tests. Il tend à rendre les tests difficiles à comprendre et difficiles à maintenir si vous introduisez une logique distincte dans la détermination de la valeur à retourner.

Je suggère que vous utilisez soit Expectation#with avec ParameterMatchers approprié pour définir explicitement des valeurs de retour pour différentes valeurs de paramètre ou utiliser la fonctionnalité StateMachine.

1

Mocha ne semble pas supporter cela. Ajoutez ceci à votre 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 

remplaceront 4 dernières lignes de votre test avec:

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) 
Questions connexes