active_decorator のdecoratorをrspecでテストする方法

active_decorator は便利なのですが、rspecでテストが上手く書けなくて、書き方を調べていた。
ただ、web上に情報が無く・・・


あ…ありのまま 今 起こった事を話すぜ!
「おれは decoratorのspecを書こうとしていたと
思ったら いつのまにかactive_decorator, rspec-rails, railsソースコードを読んでいた」

decorator のspecを書けるように色々と設定する

そのままだとspecが上手く書けないので、設定を追加しテストを書きやすくする。

application.rb でlib/のファイルを自動で読み込むようにする

config/application.rb の

    # config.autoload_paths += %W(#{config.root}/extras)

こんな感じでコメントアウトされている所を

    config.autoload_paths += %W(#{config.root}/lib)

に変更して、lib/ を読み込むようにする。*1

rspecのexample groupを追加する

spec/decorators/*.rb に対応するgroupを追加する。

lib/rspec/rails/example/decorator_example_group.rb

module RSpec::Rails
  module DecoratorExampleGroup
    extend ActiveSupport::Concern
    include RSpec::Rails::RailsExampleGroup
    include ActionView::TestCase::Behavior

    def decorate(obj)
      ActiveDecorator::Decorator.instance.decorate(obj)
      obj 
    end 

    included do
      metadata[:type] = :decorator

      before do
        ActiveDecorator::ViewContext.current = controller.view_context
      end 
    end 
  end 
end

spec_helper.rb でdecoratorの設定を追加する

spec/spec_helper.rb

RSpec.configure do |config|
    # for active_decorator
    require 'rspec/rails/example/decorator_example_group'
    config.include RSpec::Rails::DecoratorExampleGroup, :type => :decorator, :example_group => {
      :file_path => config.escaped_path(%w[spec decorators])
    } 
end

使い方の例

active_decorator のExamplesのコードに対応したspecを書いてみる。

app/decorators/user_decorator.rb

# app/decorators/user_decorator.rb
module UserDecorator
  def full_name
    "#{first_name} #{last_name}"
  end

  def link
    link_to full_name, website
  end
end

spec/decorators/user_decorator_spec.rb

describe UserDecorator do
  before do
    @user = User.create(first_name: 'sinsoku', last_name: 'listy',
                        website: 'http://d.hatena.ne.jp/sinsoku')
  end 

  subject { decorate @user }
  its(:full_name) { should eq 'sinsoku listy' }
  its(:link) { should eq '<a href="http://d.hatena.ne.jp/sinsoku">sinsoku listy</a>' }
end
実行結果
$ rspec spec/decorators/

UserDecorator
  link
    should eq "<a href=\"http://d.hatena.ne.jp/sinsoku\">sinsoku listy</a>"
  full_name
    should eq "sinsoku listy"

Finished in 0.07222 seconds
2 examples, 0 failures

追記

sinsoku/active_decorator at support_rspec https://github.com/sinsoku/active_decorator/tree/support_rspec

github でforkしてみた。
forkしたやつはspec_helper.rb に「require 'active_decorator/rspec'」を書くだけで済むようになってる

*1:decorator_example_group.rb が require さえ出来れば、どこに置いても問題ない