4

我的问题与此类似:Mocha: stubbing method with specific parameter but not for other parameters

obj.expects(:do_something).with(:apples).never
perform_action_on_obj

perform_action_on_obj不会do_something(:apples)像我预期的那样打电话。但是,它可能会调用do_something(:bananas). 如果是这样,我会遇到意外的调用失败。

我的理解是,由于我将never期望放在了末尾,因此它仅适用于特定的修改期望。然而,似乎一旦我开始嘲笑我的行为,obj我就在某种意义上“搞砸了”。

如何允许对do_something方法的其他调用obj

编辑:这是一个清晰的例子,完美地展示了我的问题:

describe 'mocha' do
  it 'drives me nuts' do
    a = mock()
    a.expects(:method_call).with(:apples)

    a.lol(:apples)
    a.lol(:bananas) # throws an unexpected invocation
  end 
end
4

4 回答 4

9

这是使用ParameterMatchers的解决方法:

require 'test/unit'
require 'mocha/setup'

class MyTest < Test::Unit::TestCase
  def test_something
    my_mock = mock()
    my_mock.expects(:blah).with(:apple).never
    my_mock.expects(:blah).with(Not equals :apple).at_least(0)
    my_mock.blah(:pear)
    my_mock.blah(:apple)
  end
end

结果:

>> ruby mocha_test.rb 
Run options: 

# Running tests:

F

Finished tests in 0.000799s, 1251.6240 tests/s, 0.0000 assertions/s.

  1) Failure:
test_something(MyTest) [mocha_test.rb:10]:
unexpected invocation: #<Mock:0xca0e68>.blah(:apple)
unsatisfied expectations:
- expected never, invoked once: #<Mock:0xca0e68>.blah(:apple)
satisfied expectations:
- allowed any number of times, invoked once: #<Mock:0xca0e68>.blah(Not(:apple))


1 tests, 0 assertions, 1 failures, 0 errors, 0 skips

总的来说,我同意你的看法:这种行为令人沮丧,并且违反了最小意外原则。也很难将上面的技巧扩展到更一般的情况,因为你必须编写一个越来越复杂的“catchall”表达式。如果您想要更直观的东西,我发现RSpec 的模拟非常好。

于 2013-07-03T16:42:19.917 回答
2

你试过阻止功能with吗?

鉴于此:

obj.stubs(:do_something).with(:apples)

给出与此相同的行为:

obj.stubs(:do_something).with { |p| p == :apples }

你可以翻转逻辑来得到你想要的:

obj.stubs(:do_something).with { |p| p != :apples }

调用 todo_something以外的任何东西:apples都会通过,而obj.do_something(:apples)会产生意想不到的调用。

于 2016-07-26T18:28:21.427 回答
0

这更像是一种破解,而不是解释摩卡行为的真正答案,但也许以下内容会起作用?

obj.expects(:do_something).with(:apples).times(0)

Mocha 将使用times 而不是完全设置基数实例变量。

于 2013-07-03T13:19:58.243 回答
0

接受的答案对我不起作用,所以我想出了在我的情况下可以解决的问题。

class NeverError < StandardError; end

obj.stubs(:do_something).with(:apples).raises(NeverError)

obj.do_something(:bananas)

begin
  obj.do_something(:apples)
rescue NeverError
  assert false, "expected not to receive do_something with apples"
end

有改进的空间,但这给出了要点并且应该很容易修改以适应大多数情况。

于 2014-10-30T02:37:18.533 回答