1. ホーム
  2. ruby-on-rails

[解決済み] Railsでコンサーンをテストする方法

2022-09-08 11:31:40

質問

私が Personable を持つRails 4アプリケーションで full_name メソッドがある場合、RSpecを使用してどのようにこれをテストしますか?

concerns/personable.rb

module Personable
  extend ActiveSupport::Concern

  def full_name
    "#{first_name} #{last_name}"
  end
end

どのように解決するのですか?

あなたが見つけた方法は、確かにちょっとした機能をテストするには有効ですが、かなり壊れやすいようです-あなたのダミークラス(実際には単なる Struct である実際のクラスのように動作するかもしれませんし、しないかもしれません。 include のような振る舞いをするかもしれません。さらに、モデルの懸念をテストしようとしている場合、データベースを適切にセットアップしない限り、オブジェクトの有効性をテストしたり、ActiveRecordコールバックを呼び出したりといったことはできません(ダミークラスにはデータベーステーブルがないため)。さらに、懸念のテストだけでなく、モデル仕様の内部での懸念の動作もテストしたいと思うことでしょう。

そこで、一石二鳥の方法はないでしょうか。RSpecの の共有サンプルグループ を使えば、実際にそれを使っているクラス (例えばモデル) に対して、あなたの懸念をテストすることができます。 を使えば、それが使われるあらゆる場所でテストができるようになります。そして、テストを一度書くだけで、その関心事を使用するすべてのモデル仕様にそれを含めることができます。あなたの場合、これは次のようになります。

# app/models/concerns/personable.rb
module Personable
  extend ActiveSupport::Concern

  def full_name
    "#{first_name} #{last_name}"
  end
end

# spec/concerns/personable_spec.rb
require 'spec_helper'

shared_examples_for "personable" do
  let(:model) { described_class } # the class that includes the concern

  it "has a full name" do
    person = FactoryBot.build(model.to_s.underscore.to_sym, first_name: "Stewart", last_name: "Home")
    expect(person.full_name).to eq("Stewart Home")
  end
end

# spec/models/master_spec.rb
require 'spec_helper'
require Rails.root.join "spec/concerns/personable_spec.rb"

describe Master do
  it_behaves_like "personable"
end

# spec/models/apprentice_spec.rb
require 'spec_helper'

describe Apprentice do
  it_behaves_like "personable"
end

このアプローチの利点は、ARコールバックの呼び出しのような、ARオブジェクトでなければできないことを懸念して行うようになると、さらに明白になります。