我的问题与此类似: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
答案 0 :(得分:8)
以下是使用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's mocks非常好。
答案 1 :(得分:1)
obj.stubs(:do_something).with(:apples)
obj.stubs(:do_something).with { |p| p == :apples }
obj.stubs(:do_something).with { |p| p != :apples }
使用do_something
之外的任何内容调用:apples
将会通过,而obj.do_something(:apples)
将产生意外调用。
答案 2 :(得分:0)
这更像是一个黑客,而不是一个解释摩卡行为的真实答案,但也许以下内容可行?
obj.expects(:do_something).with(:apples).times(0)
Mocha将使用times rather than exactly设置基数实例变量。
答案 3 :(得分: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
还有改进的余地,但这给了要点,应该很容易修改以适应大多数情况。