我的问题的主旨如下: -
我正在Ruby中编写一个Mocha模拟器,用于下面表示为“post_to_embassy”的方法。出于描述问题的目的,实际方法的作用并不是我们真正关心的问题。但是我需要模拟来返回一个动态值。下面的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
答案 0 :(得分:5)
我不确定是否有一个完美的方法。但为了让生活变得更轻松,而不是将每个可能的响应(如另一个答案所述),你可以使用Mocha的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)。但是,你不必把每个期望都排除在外,这会给你很大的自由。
答案 1 :(得分:3)
通常,在测试中指定显式返回值通常会更好。如果你引入单独的逻辑来确定返回什么值,它往往会使测试难以理解并且难以维护。
我建议您使用Expectation#with和合适的ParameterMatchers来明确定义不同参数值的返回值,或使用StateMachine功能。
答案 2 :(得分:2)
void Main()
{
var schedules = new[]{
new Schedule() { IsOn = true, DayOfWeek = DayOfWeek.Monday, TimeFrom = 540, TimeTo = 1080 },
new Schedule() { IsOn = false, DayOfWeek = DayOfWeek.Monday, TimeFrom = 780, TimeTo = 840 }
};
var byDay = schedules.GroupBy(i => i.DayOfWeek)
.Select(i =>
{
var times = i.Select(t => string.Format(@"{0:hh\:mm}-{1:hh\:mm}", TimeSpan.FromMinutes(t.TimeFrom), TimeSpan.FromMinutes(t.TimeTo)));
return string.Format("{0}: {1}", i.Key, string.Join("; ", times));
});
foreach (var day in byDay)
{
Console.WriteLine(byDay);
}
}
public class Schedule
{
public bool IsOn { get; set; }
public DayOfWeek DayOfWeek { get; set; }
public short TimeFrom { get; set; } // store time as amount of minutes since start of day
public short TimeTo { get; set; } // store time as amount of minutes since start of day
}
然后用以下代码替换测试的最后4行:
# 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
答案 3 :(得分: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."