InstanceDouble(session) (anonymous)> 予期しないメッセージを受信しました:[]=
概要
rspec の動作に問題があります。セッションを使用するサービスのテストを作成して、値を読み取り、この値を上書きしようとしています。
たとえば、テストしたいこと
class CurrentCartService
attr_reader :user, :session
def initialize(user, session)
@user = user
@session = session
end
def cart_id
{ id: session[:cart_id] }
end
def assigne_cart_to_session
session[:cart_id] = current_cart.id
end
スペック
describe CurrentCartService do
let(:current_user) { user }
let(:session) { double('session') }
let!(:cart) { create(:cart) }
subject { described_class.new current_user, session }
before do
allow(session).to receive(:[]).and_return(cart.id)
end
describe '#call' do
context 'when user is not signed' do
let(:user) { nil }
it { subject.call }
end
end
end
バインディング.こじ開け
session[:cart_id]
=> 574
session[:cart_id] = 123
RSpec::Mocks::MockExpectationError: #<InstanceDouble(session) (anonymous)> received unexpected message :[]= with (:cart_id, 123)
これを修正するにはどうすればよいですか?期待して書いてみた
expect(session).to receive(:[])
しかし、それは機能しません、それはまだ同じエラーです
解決策
このメッセージは、あなたのダブルが引数:cart_id と 123 を持つメッセージ []= を受信したが、それを予期していなかったということを示しています。
いくつかの基本的なロジックを適用してみましょう。問題は:
したがって、メッセージを取り除くためにできることは 2 つあります。
最初の方法は簡単です。session[:cart_id] = current_cart.id と書かれている 14 行目を削除するだけです。これは、[]= を呼び出している唯一の場所だからです。しかし、それはあなたがやりたいことではないと思います。
2番も簡単です。特定のメッセージを期待するように double に指示できる Expect と呼ばれるメソッドがあります。したがって、私たちがしなければならないのは、期待を設定することだけです。
適切な失敗メッセージはテスト フレームワークにおいて非常に重要であり、ありがたいことに RSpec には適切な失敗メッセージがあります。失敗メッセージには、テストを進める方法が示されます。引用したメッセージには、必要な情報がすべて含まれています。
何も考えずに、文字通りこの情報をコピー&ペーストするだけです。
expect(session).to receive(:[]=).with(:cart_id, 123)
あるいは、テストの脆弱性を少し減らし、123 をハードコーディングしないようにしたい場合は、次のようなこともできます。
expect(session).to receive(:[]=).with(:cart_id, instance_of(Integer))