LoginSignup
0
0

More than 1 year has passed since last update.

Rspecでインスタンスメソッドをinitializeメソッドを通過させずにテストさせるには

Posted at

Rspecでインスタンスメソッドをinitializeを通過させずにテストしたい!

過去の自分の行いに対しての戒め的記事。
Notベスプラ。

こんなことありませんか?

あなたは保守運用がメインのエンジニアです。これまで問題なく普通に運用されていたシステムが実は要件が違っていた、あるいは問題が起こっていたが誰も気付かず、そのままにされていて、自分がそのシステムの担当になったときに発覚し、鬼クレーム。早急に直近発生している問題を解消しないといけない、なんて状況。

障壁

これまで不完全だった処理に少し手を加えて異常値を省く処理を加えた。
当然、既存のコードをややこしくしないためにメソッドを切り出して、インスタンスメソッドが増えるなどのはある。
そしてその追加したインスタンスメソッドテストを試したいのだが、initializeメソッドに環境に依存する処理など、通したくない処理がある。そもそもその実装が正しいかはさておき、影響範囲は少なくスピーディに対応したいとき。

module ABCDE
  class FGHIJ
    def initialize(dataset = 'production')
        環境依存や外部APIとの通信を挟んだり、する処理
    end

    def new_method
        XXXXX
    end
end

プランA

テストの時のみ、ソースのインスタンスメソッドをクラスメソッド化させる。

module ABCDE
  class FGHIJ
    def initialize(dataset = 'production')
        環境依存や外部APIとの通信を挟んだり、する処理
    end

    
    def self.new_method
        XXXXX
    end
end

テスト。

require 'spec_helper'
module ABCDE
    RSpec.describe ABCDE::FGHIJ do
        describe 'new_method' do
            it 'hogehogehoge' do
                expect(ABCDE::FGHIJ.new_method)....
            end
        end
    end

テストは実行できる。一応、新しく自分が書いた部分のメソッドのテストはできる。
だがそもそもテストのためにソースコードを改変するのはキングオブナンセンス。

プランB

allocateメソッドを利用する。
allocateを使うと指定したクラスのインスタンスを生成しつつ、initializeを呼ばないということができる!!

require 'spec_helper'
module ABCDE
    RSpec.describe ABCDE::FGHIJ do
        describe 'new_method' do
            it 'hogehogehoge' do
                expect(ABCDE::FGHIJ.allocate.new_method)....
            end
        end
    end

これによりソースコードをいじることなく、テストを実行でき、initializeを通らなくて済む!

まとめ

プランBでなんとかその場を乗り切ったが、本来はその時点で設計や、前任者を既存のコードの問題を抑え込むのが最高のソリューションではある。ただし、自身の実力や置かれている状況によっては、その選択はむしろリスクとなりうることもある。自分の対応がナンセンスであることを認識しつつも、既に成立して回っているビジネスを滞りなく回し続けるためにはミニマムソリューションを選択することもある。

0
0
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
0
0