我希望我的哈希看起来像这两个中的一个:
{metadata: {SOME_UNKNOWN_KEY: {transaction_id: 123456}}}
{metadata: {transaction_id: 123456}}
如果我正在寻找密钥:transaction_id
,我知道我可以使用hash_including
来期望一个应该在特定位置的嵌套密钥,但我希望能够这样做来涵盖这两个选项:
expect(something).
to receive(some_method).
with(hash_including(metadata: hash_including_anywhere(:transaction_id)))
这可能吗?
当然有可能!
看看hash_including
是如何实现的,我们可以看到它是一个简单的匹配器类:
https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/argument_matchers.rb#L70
HashIncluding
匹配器是基于BaseHashMatcher
的,看起来如果你用某种递归方法来检查是否有密钥隐藏在更深的地方,你应该很好:
https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/argument_matchers.rb#L183
您可以从阅读hash_including
的规格开始着手:https://github.com/rspec/rspec-mocks/blob/master/spec/rspec/mocks/hash_including_matcher_spec.rb
定义自己的匹配器听起来很可怕,因为它们在我们的测试中像魔术一样工作,但实际上编写起来并没有那么复杂。