RailsチュートリアルのテストをRSpecで実施 【Micropostモデル 単体テスト編 2/3】

<!-- 
# RailsチュートリアルのテストをRSpecでやってみる 
-->

## Micropostモデル 単体テスト編 2/3

### 環境
[Userモデル 単体テスト編 1/3](https://qiita.com/shu130/items/57233462258d42566f18) に記載

#### フォルダ、使用ファイル

種類  |  ファイル名
--|--
スペック  |  spec/models/micropost_spec.rb
shared_examples  |  spec/support/shared_examples.rb
ファクトリ（ユーザ）  |  spec/support/factories/users.rb
ファクトリ（マイクロポスト）  |  spec/support/factories/microposts.rb


### アウトライン作成 1/2

- subjectの定義、その有効性の確認
- 属性やメソッドの応答(respond_to) ※shared_examples 内で作成
- メソッドの検証（userメソッド）
  - Userモデルとの belongs_to の関連付けが正しいこと

```ruby:micropost_spec.rb
# spec/models/micropost_spec.rb
require 'rails_helper'

RSpec.describe Micropost, type: :model do

  # サブジェクト
  subject(:my_post) { build(:user_post) }
  # my_post が有効であること
  it { should be_valid }
  # 属性／メソッドの応答があること
  it_behaves_like "Micropost-model respond to attribute or method"
  # userメソッドは マイクロポストを作成したユーザを返すこと
  it "user method return owner of microposts"

  # validations
  describe "validations"
    # 存在性 presence
    describe "presence"
      it "user_id should not be empty"
      it "content should not be empty"
    # 文字数 characters
    describe "characters"
      # 最大 140 文字であること
      it "content should be at most 140"

end
```

#### shared_examples の作成

```ruby:shared_examples.rb
# spec/support/shared_examples.rb
# Micropostモデル

  # 属性・メソッドの検証
  shared_examples_for "Micropost-model respond to attribute or method" do
    it { expect(page).to respond_to(:content) }
    it { expect(page).to respond_to(:user_id) }
  end
```

### スペック作成

```ruby:micropost_spec.rb
# spec/models/micropost_spec.rb

require 'rails_helper'

RSpec.describe Micropost, type: :model do

  let(:user) { create(:user) }
  # インスタンス変数(user)を明示的に渡して重複が発生しないようにする
  subject(:my_post) { build(:user_post, user: user) }

  # my_post が有効であること
  it { should be_valid }
  # 属性／メソッドの応答があること
  it_behaves_like "Micropost-model respond to attribute or method"

  # userメソッドは マイクロポストを作成したユーザを返すこと
  it "user method return owner of microposts" do
    expect(my_post.user).to eq user
  end

  # validations
  describe "validations" do
    # 存在性 presence
    describe "presence" do
      it { is_expected.to validate_presence_of :user_id }
      it { is_expected.to validate_presence_of :content }
    end
    # 文字数 characters
    describe "characters" do
      it { should validate_length_of(:content).is_at_most(140) }
    end
  end
end
```

### 実行結果

```test
$ bin/rspec spec/models/micropost_spec.rb
Running via Spring preloader in process 3262

Micropost
  should be valid
  user method return owner of microposts
  behaves like Micropost-model respond to attribute or method
    should respond to #content
    should respond to #user_id
  validations
    presence
      should validate that :user_id cannot be empty/falsy
      should validate that :content cannot be empty/falsy
    characters
      should validate that the length of :content is at most 140

Finished in 1.92 seconds (files took 1.85 seconds to load)
7 examples, 0 failures

```


--------------------------------

### 参考

- [Railsチュートリアル Rails4.0(第2版)](https://railstutorial.jp/chapters/modeling-users?version=4.0#top)

- [(書籍)leanpub - Everyday Rails - RSpecによるRailsテスト入門](https://leanpub.com/everydayrailsrspec-jp/)

--------------------------------


### 続く
#### [Relationshipモデル 単体テスト編 3/3](url)