我对 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(:[])
但还是不行,还是同样的错误
该消息告诉您,您的分身收到了该消息[]=
有参数:cart_id
and 123
但没想到。
让我们应用一些基本逻辑。问题是:
- 收到消息
- 这是没有预料到的
因此,您可以采取两件事来消除该消息:
- 不发送消息或
- 告诉分身等待消息
第一个很简单:只需删除第 14 行即可session[:cart_id] = current_cart.id
因为那是你唯一打电话的地方[]=
。但是,我认为这不是您想要做的。
第二点也很容易。有一种方法叫做expect
这可以让你告诉替身期待某条消息。所以,我们需要做的就是建立一个期望。
良好的失败消息在测试框架中非常重要,值得庆幸的是,RSpecdoes有良好的失败消息。失败消息应该告诉您如何继续进行测试,并且您引用的消息包含我们需要的所有信息:
- 引发失败的双精度名称(
session
)
- 导致失败的意外消息的名称(
[]=
)
- 甚至是传递给消息的参数(
:cart_id
and 123
)
我们所要做的就是,不假思索,直接复制粘贴以下信息:
expect(session).to receive(:[]=).with(:cart_id, 123)
或者,如果我们希望我们的测试不那么脆弱,而不是硬编码123
,我们也可以这样做:
expect(session).to receive(:[]=).with(:cart_id, instance_of(Integer))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)