我今天花了一个小时试图让 Mocha 只允许我存根一个特定的会话变量,这是Rspec 轻松允许的方式。虽然我无法找到一种方法来完成这项工作,但我确实找到了一种可能对某些人有所帮助的解决方法,具体取决于具体情况。
我的“解决方案”是在获取目标实例变量后删除会话存根:
ActionDispatch::Request::Session.any_instance.stubs(:delete).returns(state).then.returns(nonce).then.with do |sym|
ActionDispatch::Request::Session.any_instance.unstub(:delete) if sym == :login_nonce
true
end
我在这里使用的技巧是,通过知道将session.delete
在为特定操作进行的前两次调用中传递给的参数,我可以在第二次delete
调用 (for login_nonce
) 之后删除存根,因此会话开始运行又像往常一样。
构建这样一个块的另一个潜在有用的方面with
是该块具有调用者的完整上下文,因此可以直接检查或提取块内的会话内容。也就是说,如果您想要一个测试来获取blah
会话密钥的值,您应该能够编写类似的东西
ActionDispatch::Request::Session.any_instance.stubs(:[]).with do |key|
@blah = session[key] if key == :blah
true
end
据我所知,该with
块始终必须返回 true,否则 Mocha 将抛出Minitest::Assertion: unexpected invocation
异常,因为如果它已存根方法但传入的参数与它可以匹配的参数不匹配,它不知道该怎么做处理。根本问题似乎是,一旦调用stubs
,any_instance
您就不能再让 Mocha 从实际session
实例返回一个值(与 Rspec 不同,它允许使用and_call_original
上面链接的答案中的回退到原始对象)。
希望将来有人可以在其中一些想法的基础上构建一个更优雅的答案,但是由于将近 8 年过去了并且没有答案,我认为这可能是一个可用的起点。