【发布时间】:2019-08-27 04:03:44
【问题描述】:
我正在使用Rspec测试用户更改密码时会发送邮件的情况。我想检查是否只发送了 1 封邮件。我不想使用Action::Mailer.deliveries 来检查,而是想检查方法是否被调用以及调用了多少。
在搜索时,我从 rspec mock 中找到了 Test Spy:
https://github.com/rspec/rspec-mocks#test-spies
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...“>)
【问题讨论】:
-
从您的问题中不清楚
user的定义位置。但我猜user是测试开始前在数据库中创建的用户实例。而代码稍后会从数据库中加载另一个实例(同一用户的)。这意味着该方法确实不是在该user实例上调用,而是在控制器中加载的同一记录的另一个实例上调用。我猜那个方法是调用邮件程序,你为什么不模拟邮件程序? -
感谢您的回复。是的,你是对的,来自 rspec 的实例和来自控制器的实例是不同的。我可以使用
expect_any_instance_of(User)让它工作
标签: ruby-on-rails ruby rspec mocking rspec-rails