ruby-on-rails - Rspec测试调用方法发送再确认指令
问题描述
我正在使用 Rspec 测试用户更改密码时的情况,邮件将被发送。我想检查是否只发送了 1 封邮件。我不想Action::Mailer.deliveries
用来检查,而是想检查是否调用了方法以及调用了多少。
在搜索时我Test Spy
从 rspec mock 中找到:
https ://github.com/rspec/rspec-mocks#test-sies
describe 'PUT /email' do
include_context 'a user has signed in', { email: 'old-email@example.com', password: 'correct_password' }
context 'correct new email, correct password' do
before do
allow(user).to receive(:send_reconfirmation_instructions)
end
it do
should == 302
expect(user.reload.unconfirmed_email).to eq 'new-email@example.com'
expect(user).to receive(:send_reconfirmation_instructions).once
end
end
end
但我得到了错误:
Failure/Error: expect(user).to receive(:send_reconfirmation_instructions)
(#<User id: 1269, email: “old-email@example.com”, created_at: “2019-08-27 03:54:33", updated_at: “2019-08-27 03:54:33”...“>).send_reconfirmation_instructions(*(any args))
expected: 1 time with any arguments
received: 0 times with any arguments
send_reconfirmation_instructions
此功能来自设计:https ://github.com/plataformatec/devise/blob/master/lib/devise/models/confirmable.rb#L124-L130
我做到了binding.pry
,我确定测试在这个函数内跳转,但 rspec 仍然失败。
编辑:我可以这样写:
describe 'PUT /email' do
include_context 'a user has signed in', { email: 'old-email@example.com', password: 'correct_password' }
context 'correct new email, correct password' do
before do
expect_any_instance_of(User).to receive(:send_reconfirmation_instructions).once
end
it do
should == 302
expect(user.reload.unconfirmed_email).to eq 'new-email@example.com'
# expect(user).to receive(:send_reconfirmation_instructions).once
end
end
end
但是我遇到了另一个错误:
Failure/Error:
(#<User user_id: 1418, email: “old-email@example.com”...“>).send_reconfirmation_instructions(#<User user_id: 1418, email: “old-email@example.com” ...“>)
expected: 1 time with any arguments
received: 2 times with arguments: (#<User user_id: 1418, email: “old-email@example.com”, id: 1323...“>)
解决方案
您正在检查用户是否已收到消息的行应为:
expect(user).to have_received(:send_reconfirmation_instructions).once
代替:
expect(user).to receive(:send_reconfirmation_instructions).once
您所说的前者expect(obj).to have_received(:msg)
要求您断言该消息已按您的意图被调用。
另一方面,您说后者expect(obj).to receive(:msg)
是一种在动作之前设置期望的方法,即代替 theallow(obj).to receive(:msg)
而不需要断言它是在动作之后调用的。规范运行后,它会自动断言它是否被调用。
这解释了您在指定时遇到的错误
expect(user).to receive(:send_reconfirmation_instructions).once
因为该行之后没有代码将该消息发送到user
,在规范之后得到验证。
推荐阅读
- tableau-api - 默认情况下允许用户在 tableau 中移动地图的配置?
- javascript - 如何使用 nodejs 在 cosmosdb 中进行批量插入?
- reactjs - 在 React.useState 中保存对象
- javascript - 如何在打字稿中定义一个zip函数
- android - 互联网签入对话框
- matlab - 在matlab中以hh:mm格式在x轴上绘制一组数据和时间
- node.js - 关于通过 knex 使用 node.js 连接到我的 Postgres 的问题
- java - C# 加密到 Java 解密
- swift - (Swift/FireStore)如何将 URL 放入 StringArray
- python - 将类方法放在 RQ 队列上时出现 Python rq 错误