Techioz Blog

rspec でハッシュの配列に対してマッチャーとマッチャーを使用する方法

概要

ハッシュの配列があり、その配列には特定のキーを持つ特定の順序で正確に特定の数のハッシュがあることを主張しようとしています。

それで、果物の配列があるとします。

fruits = [
  { name: 'apple', count: 3 },
  { name: 'orange', count: 14 },
  { name: 'strawberry', count: 7 },
]

hash_include (またはそのエイリアスである include) を指定して eq matcher を使用すると、アサーションが失敗します。

# fails :(
expect(fruits).to eq([
  hash_including(name: 'apple'),
  hash_including(name: 'orange'),
  hash_including(name: 'strawberry'),
])

これがうまくいかないのは奇妙で、いつもそれを回避する方法を見つけて先に進んできましたが、しばらく気になっていたので、今回それについて投稿することにしました。

これは明らかに機能しますが、私は他の構文の方が好きです。それがこれらのマッチャーの重要な点だからです。データ構造を手動で変換する必要がなく、より読みやすい仕様が得られます。

fruit_names = fruits.map { |h| h.fetch(:name) }
expect(fruit_names).to eq(['apple', 'orange', 'strawberry'])

contains_exactly と include は機能しますが、配列の正確なサイズと要素の順序が気になり、それらはアサートできません。

# passes but doesn't assert the size of the array or the order of elements
expect(fruits).include(
  hash_including(name: 'apple'),
  hash_including(name: 'orange'),
  hash_including(name: 'strawberry'),
)

# passes but doesn't assert the exact order of elements
expect(fruits).contain_exactly(
  hash_including(name: 'apple'),
  hash_including(name: 'orange'),
  hash_including(name: 'strawberry'),
)

解決策

matchを使用する必要があるようです

fruits = [
  { name: 'apple', count: 3 },
  { name: 'orange', count: 14 },
  { name: 'strawberry', count: 7 },
]

expect(fruits).to match([
  include(name: 'apple'),
  include(name: 'orange'),
  include(name: 'strawberry'),
])

配列要素が欠落しているか余分な場合、このテストは失敗します。

一部のハッシュに指定されたキーと値のペアが含まれていない場合、このテストは失敗します。

配列要素の順序が間違っている場合、このテストは失敗します。