19349


Rails4.0に上げてRspec2.99にしたところテストでエラーが出るようになりました。

[code]

    エラー。, can't convert RSpec::Mocks::Double to Array (RSpec::Mocks::Double#to_ary gives RSpec::Mocks::Double)
    2015/11/25 15:31:39 [INFO] ::
        /poge/hoge/.rbenv/versions/2.2.3/gemsets/4.0/gems/actionpack-4.0.13/lib/action_view/helpers/form_options_helper.rb:347:in `Array'
        /poge/hoge/.rbenv/versions/2.2.3/gemsets/4.0/gems/actionpack-4.0.13/lib/action_view/helpers/form_options_helper.rb:347:in `block in options_for_select'
        /poge/hoge/.rbenv/versions/2.2.3/gemsets/4.0/gems/actionpack-4.0.13/lib/action_view/helpers/form_options_helper.rb:346:in `map'
        /poge/hoge/.rbenv/versions/2.2.3/gemsets/4.0/gems/actionpack-4.0.13/lib/action_view/helpers/form_options_helper.rb:346:in `options_for_select'
        /poge/hoge/.rbenv/versions/2.2.3/gemsets/4.0/gems/actionpack-4.0.13/lib/action_view/helpers/tags/select.rb:22:in `render'
        /poge/hoge/.rbenv/versions/2.2.3/gemsets/4.0/gems/actionpack-4.0.13/lib/action_view/helpers/form_options_helper.rb:156:in `select'
        /poge/hoge/.rbenv/versions/2.2.3/gemsets/4.0/gems/actionpack-4.0.13/lib/action_view/helpers/form_options_helper.rb:774:in `select'
        /poge/hoge/workspace/version/app/pogeapp/app/helpers/common_form_builder.rb:157:in `block in select_frame'
    
[/code]

Rspecを[バージョンアップ](https://www.ruby-forum.com/topic/209109)すれば解決するのでしょうか？  
selectボックスを表示する箇所でエラーが出るようになりました。実際に表示してもエラーにはなりません。

実コードデバックしたやつです。listsに配列を入れてセレクトボックスで出そうとしてるだけです。

[code]

    157       select(:hogeid, lists, options, {:class => span12}) +
    (byebug) p lists
    [Hoge:0x3fcd6a333844 @name="Hoge_11"]
    (byebug) p options
    {}
    
[/code]

テストコード、レスポンスがエラーにならないことを確かめてます。

[code]

    let(:lists){mock_model(Hoge).as_null_object}
    
         before(:each) do
           get :new_hogehoge, params
         end
         it "エラーにならない" do
           response.should be_success
         end
    
[/code]


CC BY-SA 3.0
2015-11-25T14:29:12.813
19299
2015-11-26T23:37:20.257
2015-11-26T01:10:50.467
10851
10851
question
ruby-on-rails ruby rspec
Rspecでcan't convert RSpec::Mocks::Double to Arrayエラーが出る


詳しい理由はわかりませんが、mock_model + as_null_object
にすると、事前にセットアップしていないメソッド呼び出しは常に自分自身（つまり null object）を返す仕様になっているようです。（最新版でも同様）

<https://github.com/rspec/rspec-activemodel-
mocks/blob/master/spec/rspec/active_model/mocks/mock_model_spec.rb#L286>

[code]

    it "returns self for any unprepared message" do
      @model.as_null_object.tap do |x|
        expect(x.non_existant_message).to be(@model)
      end
    end
    
[/code]

また、質問のエラーはnull objectを引数（下記コードの`r`）にして Kernel#Array() を呼びだしているところで発生しています。

action_view/helpers/form_options_helper.rb:347:in `Array'

[code]

    selected, disabled = extract_selected_and_disabled(selected).map do |r|
      Array(r).map { |item| item.to_s }
    end
    
[/code]

Kernel#Array() は渡されたオブジェクトに対して、`to_ary`と`to_a`を呼び出します。  
配列以外のオブジェクトはこの呼び出しを無視すべきなのですが、null objectは（意味もなく）自分自身を返してしまうため、エラーが起きたようです。

というわけで、null
objectに対して、`to_ary`と`to_a`の呼び出しを無視する（nilを返す）ように振る舞いを定義すると、おそらくうまくいきます。

[code]

    let(:lists) do
      mock_model(Hoge).as_null_object.tap do |hoge|
        allow(hoge).to receive(:to_ary).and_return(nil)
        allow(hoge).to receive(:to_a).and_return(nil)
      end
    end
    
[/code]

こちらの環境（RSpec 2.99 + Rails 4.0.13）ではこれでうまくいきました。  
一度試してみてください。


CC BY-SA 3.0
2015-11-26T23:37:20.257
19349
2015-11-26T23:37:20.257
85
19299
answer