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

时间:2019-04-07 15:17:38

标签: ruby-on-rails ruby rspec ruby-on-rails-5

我的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(:[])

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

1 个答案:

答案 0 :(得分:0)

该消息告诉您,您的双打收到了带有参数[]=:cart_id的消息123,但没想到。

让我们应用一些基本逻辑。问题是:

  1. 接收消息
  2. 那没想到的

因此,您可以做两件事来摆脱该消息:

  1. 不发送消息或
  2. 告诉双打,期待收到消息

第一个很简单:只需删除第14行显示session[:cart_id] = current_cart.id,因为这是您唯一呼叫[]=的地方。但是,我认为这不是您想要做的。

第二个也很容易。有一种称为expect的方法,该方法使您可以告诉双精度字符期望某条消息。因此,我们要做的就是建立期望。

好的故障消息在测试框架中确实很重要,并且值得庆幸的是,RSpec 确实具有好的故障消息。失败消息应该告诉您如何继续进行测试,并且所引用的消息包含我们需要的所有信息:

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

我们所要做的就是根本不考虑它,只是复制并粘贴以下信息:

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

或者,如果我们希望测试不那么脆弱并且不对123进行硬编码,我们还可以执行以下操作:

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