61
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

rspec 「let」と「let!」の違い

Posted at

##はじめに
業務でRSpecでテストコードを書いています。
先日「あれ、通るはずのテストが通らない。。。(´・ω・`)」と思ったら「let!」の「!」を付け忘れていました。
備忘録として、letとlet!の違いをまとめておきます。

##let
letは、定義した定数が初めて使われたときに評価されます。

sample_spec.rb
#composerが複数のsongを持つものとする
Rspec.describe Sample do
  let(:composer) { create(:composer) }
  let(:composer_song) { create(:song, composer: composer, title: 'きらきら星') }
    it '〜〜' do
      expect(composer).to ~~
    end
  end
end

ここでは、expect(composer).tocomposer が出てきたタイミングで、letで定義したcomposerがcreateされる、ということになります。遅延評価と言うそうです。

以下のコードでは、テストは失敗します。

sample_spec.rb
#composerが複数のsongを持つものとする
Rspec.describe Sample do
  let(:composer) { create(:composer) }
  let(:composer_song) { create(:song, composer: composer, title: 'きらきら星') }
    it 'composerがcomposer_songを持っていること' do
      expect(composer.song.first.title).to eq 'きらきら星'
    end
  end
end

composer_songはcreateされておらず、composer.song.firstは空になり、エラーになります。

##let!
let!は、各テストのブロック実行前に定義した定数を作ります。
letの遅延評価に対して事前評価とも言うそうです。
先程のテストを成功させるには、「!」を付けてあげれば良いのです。

sample_spec.rb
#composerが複数のsongを持つものとする
Rspec.describe Sample do
  let(:composer) { create(:composer) }
  let!(:composer_song) { create(:song, composer: composer, title: 'きらきら星') }
    it 'composerがcomposer_songを持っていること' do
      expect(composer.song.first.title).to eq 'きらきら星'
    end
  end
end

before(:each) doと同じように使えるのですね。

##まとめ
・letは、定義した定数が初めて出てきたときにcreateされる
・let!は、各ブロック実行前に定数をcreateする

なんとなく「遅延評価」という言葉は知っていたものの、実際にハマってみて改めてその意味を理解できた気がします。。

間違っている点等あればご指摘いただけますと幸いです。

###余談
letで定義してspecが落ちるのでデバック用でppを付けて定数を出力すると、当たり前なのですがテストは通ります。
こんな感じ

sample_spec.rb
#composerが複数のsongを持つものとする
Rspec.describe Sample do
  let(:composer) { create(:composer) }
  let(:composer_song) { create(:song, composer: composer, title: 'きらきら星') }
    it 'composerがcomposer_songを持っていること' do
      pp composer_song
      expect(composer.song.first.title).to eq 'きらきら星'
    end
  end
end

pp composer_songcomposer_songって何者?→let(:composer_song)に辿り着き、createされるというわけですね。

61
32
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
61
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?