ruby InstanceDouble(session)(anonymous)>收到意外消息:[]= with

aiqt4smr  于 2023-11-18  发布在  Ruby
关注(0)|答案(2)|浏览(106)

我有一个问题与rspec行为。我试图写测试的服务,我使用session,为读取一些值,并覆盖此值。
比如我想测试的

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

字符串
spec

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


binding.pry

session[:cart_id]
=> 574
session[:cart_id] = 123
RSpec::Mocks::MockExpectationError: #<InstanceDouble(session) (anonymous)> received unexpected message :[]= with (:cart_id, 123)

的字符串
如何解决这个问题?我试着写一些expect

expect(session).to receive(:[])


但它不工作,它仍然是相同的错误

lf5gs5x2

lf5gs5x21#

该消息告诉你,你的替身收到了带有参数:cart_id123的消息[]=,但没有预料到它。
让我们应用一些基本的逻辑。问题是:
1.接收消息
1.出乎意料的
所以,有两件事你可以做,以摆脱消息:
1.不发送消息或
1.告诉替身等消息
第一个很简单:删除第14行session[:cart_id] = current_cart.id,因为这是你唯一调用[]=的地方。然而,我不认为这是你想做的。
第二个方法也很简单,有一个叫做expect的方法,它允许你告诉一个double去期望某个消息,所以我们需要做的就是设置一个期望值。
好的失败消息在测试框架中非常重要,谢天谢地,RSpec * 确实有好的失败消息。失败消息应该告诉你如何继续你的测试,你引用的消息包含了我们需要的所有信息:

  • 引发失败的double的名称(session
  • 导致失败的意外消息的名称([]=
  • 甚至传递给消息的参数(:cart_id123

我们所要做的就是,甚至不用考虑它,字面上只是复制和粘贴这些信息:

expect(session).to receive(:[]=).with(:cart_id, 123)

字符串
或者,如果我们希望测试不那么脆弱,而不是硬编码123,我们也可以这样做:

expect(session).to receive(:[]=).with(:cart_id, instance_of(Integer))

egmofgnx

egmofgnx2#

我不明白你选择的设计,所以我只回复你得到的错误。
您允许session接收:[]。错误是session接收了:[]=
因此,您可以允许session接收:[]

before do
    allow(session).to receive(:[]=).and_return(cart.id)
  end

字符串
注意:我不会使用expect,因为它仅仅是为了设置测试期望,而不是测试,这是你想用allow实现的。

相关问题