2024-01-28

RSpec で module のテストを書く方法

目次

例として Calculatable というモジュールの関数をテストしたいとします。

# calculatable.rb
module Calculatable
  def add(a, b)
    a + b
  end
end

実際にこのモジュールを include しているクラスに対してテストを書くということもできますが、クラスの関心事も入ってきてしまい書きづらいケースも多いでしょう。

以下のようなコードで module 単体のテストを書けます。

# spec/calculatable_spec.rb
RSpec.describe Calculatable do
  let(:klass) do
    Class.new { include Calculatable }
  end

  describe '#add' do
    it 'returns the sum of two numbers' do
      expect(klass.new.add(1, 2)).to eq 3
    end
  end
end

Class.new で、無名のクラスを生成できます。さらにブロックを渡すと、そのクラスのコンテキストでブロックを実行してくれます。つまりこれで、Calculatable モジュールを include しただけのクラスを作ることができます。名前空間も汚さないので安心です。

別の方法

クラスは使わず、オブジェクトに対して Object#extend でモジュールを特異メソッドとして追加する方法もあります。

# spec/calculatable_spec.rb
RSpec.describe Calculatable do
  let(:obj) do
    Object.new.extend(Calculatable)
  end

  describe '#add' do
    it 'returns the sum of two numbers' do
      expect(obj.add(1, 2)).to eq 3
    end
  end
end

こちらは都度の new が不要でより短くテストが書けますね。