はじめに
Rails のテストツール Rspec を使ってみました。 使用中に、expected `User.count` to have changed by 1, but was not given a block と言うエラーにハマったので備忘録として残します。問題のソースコード
これがエラーの出るソースコードです。エラーのでるソース
expect(
find('input[name="commit"]').click
).to change{User.count}.by(1)
エラーの内容
エラー expected `User.count` to have changed by 1, but was not given a block 翻訳 `User.count`が1変更されると予想されましたが、ブロックが与えられませんでしたchange マッチャを使うときは、expectをブロックにしなきゃいけないよって事でした。
つまり、()だと引数を渡してるので、{}にして動作そのものを渡せって事みたいです。
それを踏まえて、ソースを書き直します。
正常に動作するソース
expect{
find('input[name="commit"]').click
}.to change{User.count}.by(1)
これで実行したら正常に動作しました。
ブロックは メゾット名 do / end って書き方もあるのでついでにこのようにソースを書き換えて実行しました。
実験1
expect do
find('input[name="commit"]').click
end.to change{User.count}.by(1)
実験1結果 成功!!
27: # }.to change{User.count}.by(1)
28: #実験
29: # expect(
30: # find('input[name="commit"]').click
31: # ).to change{User.count}.by(1)
=> 32: binding.pry
33: expect do
34: find('input[name="commit"]').click
35: end.to change{User.count}.by(1)
36:
37:
[1] pry(#<RSpec::ExampleGroups::Nested::Nested>)> exit
正しい情報を入力すればユーザー新規登録ができてトップページに移動する
ユーザー新規登録ができないとき
誤った情報ではユーザー新規登録ができずに新規登録ページへ戻ってくる
Finished in 17.61 seconds (files took 1.73 seconds to load)
2 examples, 0 failures
メゾット名 do / end でも正常に動くことを確認しました。
ついでに、もう一つ確認しました。chage のブロックを do / end に変更。
実験2
expect do
find('input[name="commit"]').click
end.to change do User.count end.by(1)
実験2結果 失敗。。。
Failure/Error:
expect do
find('input[name="commit"]').click
end.to change do User.count end.by(1)
SyntaxError:
Block not received by the `change` matcher. Perhaps you want to use `{ ... }` instead of do/end?
構文エラーになりました。
エラーの内容
エラー Block not received by the change
matcher. Perhaps you want to use { ... }
instead of do/end?
翻訳 change
マッチャーがブロックを受信していません。 おそらく、do / endの代わりに {...}
を使用したいですか?
結果は、{} 使えって言われました。
わざわざ、do / end なんて使わず{}で統一するのが良さそうですね。
まとめ
- ()だと引数になって、{}だとブロックをわたす。
- expect {}.to change{}.by() と書く。
- do / end は使わない。