1

直接与大脑交互并不容易,所以我使用了一些网关模式和一些依赖倒置。

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:类“Mocha::Mock”的未定义方法“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)电话和摩卡咖啡通过使用method_missing或其他东西起作用。唯一的解决方案似乎是更改设置

class NumberCruncherTest

  class FakeBrain
    def multiply_by_100; end
  end

  def setup
    @brain = FakeBrain.new
    @cruncher = NumberCruncher.new @brain
  end

  # ...
end

但是,我认为这种解决方案很糟糕。它很快就变得一团糟,并且Fake*在我的测试中放置了大量的课程。有没有更好的方法来用摩卡做到这一点?

4

1 回答 1

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应该可以在您的情况下正常工作,并且可以与任何模拟框架一起使用。

顺便说一句,我猜你的测试为什么不起作用是因为 mocha 没有存根 proc 方法,而且是好的,因为如果你将一个方法转换为一个 proc,你不再测试一个方法调用,而是一个 proc 调用。

因为每个人都喜欢基准测试:

@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
于 2013-07-15T22:53:44.510 回答