ruby-on-rails - RSpec:迭代器中的存根方法
问题描述
我想学习如何使用存根。
class SomeClass
attr_reader :current_user
def initialize(current_user:)
@current_user = current_user
end
def deliver
subscribers.each do |user|
DailyEmail.new(recipient: user).deliver
end
201
end
private
def subscribers
User.all.select(&:email_notifications_enabled?)
end
end
什么是测试 DailyEmail 新的正确方法,从 SomeClass 调用的传递方法。如果订阅者是活动记录关系,我如何测试每种方法?我如何检查迭代器后的状态返回?
我奇怪的解决方案:
RSpec.describe SomeClass do
let(:current_user) { 'user' }
subject { described_class.new(current_user: current_user) }
describe '#deliver' do
let(:subscribers) { ['test2', 'test1'] }
context 'when `each`, `new`, `deliver` methods called in controller `deliver` method' do
it 'calls methods' do
allow(subscribers).to receive(:each)
subscribers.each do |user|
the_double = instance_double(DailyEmail)
expect(DailyEmail).to receive(:new).and_return(the_double).with(recipient: user)
expect(the_double).to receive(:deliver)
expect(subscribers).to have_received(:each)
subject.deliver
end
end
end
end
end
我写了一些东西,但这个实现对我来说似乎很糟糕。我不明白如何处理迭代器以及如何测试状态。请给一些提示
解决方案
这里有几件事。
首先是您的控制器状态消息是错误的。您现在所做的是返回 201 正文,而不是状态。它应该返回 200,您正在执行一个发送电子邮件的操作,而不是创建对象。如果您不想返回除了肯定的错误消息之外的任何其他内容并且不处理错误消息(您应该这样做),您应该替换201
为:render status: 200
您的测试目前并没有真正测试任何东西。如果您的订阅者方法有错误,它不会捕获它,如果您的邮件类有一个错误,您将不会捕获它,那么重点是什么。
对于控制器本身的逻辑,您应该正确循环通过要传递的邮件,并检查它们是否已传递https://relishapp.com/rspec/rspec-rails/docs/mailer-specs或拆分测试在两个。您使用控制器测试测试快乐路径并为电子邮件类创建另一个测试。
运行控制器测试的正确方法是使用请求规范,并期望正确的响应代码。请注意,如果您在测试数据库中启用了订阅者,它将返回 200,如果没有订阅者,它也只会返回 200。整个代码仍在测试中。如果订阅方法中有错误,它将返回 500 错误。https://relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec
要正确测试控制器测试,您需要在测试数据库中创建对象,然后循环遍历它们,而不是尝试像那样模拟它。例如,您可以使用 FactoryBot 执行此操作,或者您甚至可以删除用户模型,如果您由于某种原因无法像这样添加 FactoryBot;取决于您在邮件类中所做的事情。
before :each do
stub_const('User', MockedUserModel)
end
class MockedUserModel < User
def all
arr_of_mocked_users = []
arr_of_mocked_users << User.new(name: 'mocked_user_1', id: 1)
arr_of_mocked_users << User.new(name: 'mocked_user_1', id: 2)
arr_of_mocked_users
end
def email_notifications_enabled?
true
end
end
推荐阅读
- android - 短信权限问题再次浮出水面,Play 商店现在拒绝了我的应用更新
- python - 从 PyCharm 中的 PYTHONPATH 中删除路径无法正常工作?
- swift - 循环遍历数组的范围
- c# - 使用 AudioConfig 和 PushAudioOutputStreamCallback 时,SpeakTextAsync 抛出异常“在垃圾收集委托上进行了回调”
- java - 如何在 Eclipse 上恢复已删除的项目?
- http - CORS Cookie 未保存在浏览器中
- javascript - Puppeteer:正确选择内部文本
- java - 试图阻止 ArrayList 在方法调用上加倍
- ios - UIAlertController 上的 UITapGestureRecognizer 未触发
- python - 将 pydoc HTML 集成到 Jupyter 中,忽略样式