open module による置き換え

コラボレーションテストで、テスト対象のクラスにincludeされたメソッドをモック化する際
Dependency Injectionでやろうとするのはなんか手間だなと思って、前回はテスト対象のクラスに手を加えて逃げた.


今回は別解でオープンモジュール??(オープンクラス)の機能を使って、テスト範囲外のモジュールに手を加えて偽物にしてしまって回避.
こちらのほうが、テスト対象クラス自身に手を加えていないので、よりベターな方法かなと.

OpenFromMenuがChoiceSwitchCommandでインクルードしているモジュール.
ChoiceSwitchCommandが一番テストしたい範囲.OpenFromMenuモジュールを偽物に置き換えている.

module QuickMate
・・・
  # mock
  #   ChoiceSwitchCommand include OpenFromMenu
  module OpenFromMenu
    attr_reader :paths
    def open_menu(path_line_views)
      @paths = path_line_views.collect { |path_line_views| 
        path_line_views[0]
      }
    end    
  end

require File.dirname(__FILE__) + '/../../lib/quickmate/choice_switch_command'

module QuickMate
  describe ChoiceSwitchCommand, "file choice targets" do
    def choice(expected)
      Pairs.new(expected)
    end
    
    before(:each) do
      @command = ChoiceSwitchCommand.new
      @fixtures_path = "#{ENV["TM_PROJECT_DIRECTORY"]}/Support/fixtures/exist_file"
    end

    it "should choice many file when current file is lib (one to many)" do
      @command.open_pair("#{@fixtures_path}/lib/foo/one_to_many.rb")
      @command.should choice([
                    "#{@fixtures_path}/spec/foo/feature_1-one_to_many_spec.rb",
                    "#{@fixtures_path}/spec/foo/feature_2-one_to_many_spec.rb",
                    "#{@fixtures_path}/spec/foo/one_to_many_spec.rb"])
    end

    it "should choice one file when current file is spec (many to one)" do
      @command.open_pair("#{@fixtures_path}/spec/foo/feature_1-one_to_many_spec.rb")
      @command.should choice(["#{@fixtures_path}/lib/foo/one_to_many.rb"])
    end

    it "should choice one file when current file is lib (one to one)" do
      @command.open_pair("#{@fixtures_path}/lib/foo/one_to_one.rb")
      @command.should choice(["#{@fixtures_path}/spec/foo/one_to_one_spec.rb"])
    end
  end
  
  # mock
  #   ChoiceSwitchCommand include OpenFromMenu
  module OpenFromMenu
    attr_reader :paths
    def open_menu(path_line_views)
      @paths = path_line_views.collect { |path_line_views| 
        path_line_views[0]
      }
    end    
  end
  
  class Pairs
    def initialize(expected)
      @expected = expected
    end

    def matches?(actual)
      @actual = actual.paths
      @actual.should == @expected
      true
    end

    def failure_message
      "expected #{@actual.paths.inspect} to choice #{@expected.inspect}, but it didn't"
    end

    def negative_failure_message
      "expected #{@actual.paths.inspect} not to choice #{@expected.inspect}, but it did"
    end
    
    def description
      "choice #{@actual} <=> #{@expected}"
    end
  end  
end