直接与大脑交互并不容易,因此我使用了一些网关模式和一些依赖性反转。
NumberCruncher
是我Brain
类的包装器。
class NumberCruncher
def initialize brain = Brain.new
@brain = brain
end
def times_one_hundred *numbers
numbers.map &@brain.method(:multiply_by_100)
end
end
我在测试时遇到错误:
NameError:未定义的方法`multiply_by_100'对于“摩卡::模拟'
”
这是测试
class NumberCruncherTest
def setup
@brain = mock
@cruncher = NumberCruncher.new @brain
end
def test_times_one_hundred
@brain.expects(:multiply_by_100).with(1).returns(100)
@brain.expects(:multiply_by_100).with(2).returns(200)
@brain.expects(:multiply_by_100).with(3).returns(300)
assert_equal [100, 200, 300], @cruncher.times_one_hundred(1,2,3)
end
end
由于&@brain.method(:multiply_by_100)
调用我正在假设,而mocha使用method_missing
或其他东西。唯一的解决方案似乎是更改设置
class NumberCruncherTest
class FakeBrain
def multiply_by_100; end
end
def setup
@brain = FakeBrain.new
@cruncher = NumberCruncher.new @brain
end
# ...
end
但是,我认为这种解决方案很糟糕。它变得很乱,它在我的测试中放了大量的Fake*
类。用mocha有没有更好的方法呢?
答案 0 :(得分:0)
我认为您可以通过更改方法来解决问题。
这
numbers.map &@brain.method(:multiply_by_100)
# which is equivalent to (just to understand the rest of my answer)
numbers.map {|number| @brain.method(:multiply_by_100).to_proc.call(number) }
到
numbers.map {|number| @brain.send(:multiply_by_100, number) }
这实际上更好,因为您的代码存在一些问题。将对象方法转换为proc(正如您所做的那样),有点将对象的状态冻结到proc中,因此实例变量的任何更改都不会生效,并且可能会更慢。 send
应该适用于您的案例,并适用于任何模拟框架。
因为每个人都喜欢基准:
@o = Object.new
def with_method_to_proc
@o.method(:to_s).to_proc.call
end
def with_send
@o.send(:to_s)
end
def bench(n)
s=Time.new
n.times { yield }
e=Time.new
e-s
end
bench(100) { with_method_to_proc }
# => 0.000252
bench(100) { with_send }
# => 0.000106
bench(1000) { with_method_to_proc }
# => 0.004398
bench(1000) { with_send }
# => 0.001402
bench(1000000) { with_method_to_proc }
# => 2.222132
bench(1000000) { with_send }
# => 0.686984