Ruby on rails Rspec:测试以确保通知电子邮件在无效记录之后*未*发送(ActiveRecord::RecordInvalid:)
我正在尝试测试,以确保邮件程序在无效记录之后没有发送通知,但在测试完成之前,我一直在获取以下错误信息 “ActiveRecord::RecordInvalid: 我怎样才能正确地测试它 编辑:以下是发送邮件的代码:Ruby on rails Rspec:测试以确保通知电子邮件在无效记录之后*未*发送(ActiveRecord::RecordInvalid:),ruby-on-rails,rspec,Ruby On Rails,Rspec,我正在尝试测试,以确保邮件程序在无效记录之后没有发送通知,但在测试完成之前,我一直在获取以下错误信息 “ActiveRecord::RecordInvalid: 我怎样才能正确地测试它 编辑:以下是发送邮件的代码: after_create :send_email_notification private def send_email_notification if self.shop.email_notifications NotificationMai
after_create :send_email_notification
private
def send_email_notification
if self.shop.email_notifications
NotificationMailer.user_notification(self).deliver_now
end
end
end
因此,这样做的目的是设置您的期望值,然后将无效用户属性发布到用户控制器创建方法
当然,如果您在用户模型中正确设置了验证,并且随后没有调用NotificationMailer.user\u notification,则不应允许帖子创建记录
请注意,attributes\u for是另一种FactoryGirl方法,您可以使用该方法将工厂属性作为控制器参数进行排列和传递
现在!为什么它不适用于您原来的方法?
这是因为FactoryGirl抱怨它无法创建记录,这是绝对合乎逻辑的,因为您正在尝试创建无效用户。失败的错误与测试电子邮件通知无关,而是与您设置Factory的方式有关
最后一点注意!如果您运行测试时,它会抱怨:
"NoMethodError: undefined method `post' for #<RSpec::ExampleGroups"
“NoMethodError:undefined method`post'for#下面是我用来测试用例的一些代码:您可以将其复制并粘贴到文件中,然后在其上运行rspec
。我希望我对Rails应用程序中你没有透露的部分所做的假设不会太离谱
require 'active_record'
require 'factory_girl'
require 'rspec'
ActiveRecord::Base.establish_connection(
adapter: 'sqlite3', database: ':memory:'
)
class User < ActiveRecord::Base
has_one :shop
validates :email, presence: true
after_create :send_notification
private
def send_notification
if shop.email_notifications
NotificationMailer.user_notification(self).deliver_now
end
end
end
class Shop < ActiveRecord::Base
belongs_to :user
end
ActiveRecord::Schema.define do
create_table :users do |t|
t.string :email
end
create_table :shops do |t|
t.boolean :email_notifications
t.belongs_to :user
end
end
FactoryGirl.define do
factory :user do
email "test@example.com"
shop
factory :invalid_user do
email nil
end
end
factory :shop do
email_notifications true
end
end
RSpec.describe User do
context 'on save' do
let(:mailer) { double('mailer') }
before do
# You probably won't need this stub_const since the class will exist
# in your app
stub_const('NotificationMailer', Class.new)
allow(NotificationMailer).to \
receive(:user_notification).with(user).and_return(mailer)
end
context 'when user is valid' do
let(:user) { FactoryGirl.build(:user) }
it 'calls to send email notifications' do
expect(mailer).to receive(:deliver_now)
user.save
end
end
context 'when user is invalid' do
let(:user) { FactoryGirl.build(:invalid_user) }
it 'does not call to send email notifications' do
expect(mailer).to_not receive(:deliver_now)
user.save
end
end
end
end
由于触发了异常,这意味着存在验证问题,这是您尝试保存无效的_用户后的预期行为。这本身就确保了没有邮件被发送。问题是您在代码中的何处声明了发送电子邮件?是在保存之后,还是在创建之后。那么,我该如何为此编写规范呢?期望无效用户无效?你能分享你实际发送邮件的部分代码吗。等等-现在我得到“NoMethodError:未定义#的方法'post';这可能是因为您的规范不在规范/控制器之下。我已编辑了答案,以包含指向stackoverflow答案的链接,该答案演示了如何解决此问题的说明。
"NoMethodError: undefined method `post' for #<RSpec::ExampleGroups"
require 'active_record'
require 'factory_girl'
require 'rspec'
ActiveRecord::Base.establish_connection(
adapter: 'sqlite3', database: ':memory:'
)
class User < ActiveRecord::Base
has_one :shop
validates :email, presence: true
after_create :send_notification
private
def send_notification
if shop.email_notifications
NotificationMailer.user_notification(self).deliver_now
end
end
end
class Shop < ActiveRecord::Base
belongs_to :user
end
ActiveRecord::Schema.define do
create_table :users do |t|
t.string :email
end
create_table :shops do |t|
t.boolean :email_notifications
t.belongs_to :user
end
end
FactoryGirl.define do
factory :user do
email "test@example.com"
shop
factory :invalid_user do
email nil
end
end
factory :shop do
email_notifications true
end
end
RSpec.describe User do
context 'on save' do
let(:mailer) { double('mailer') }
before do
# You probably won't need this stub_const since the class will exist
# in your app
stub_const('NotificationMailer', Class.new)
allow(NotificationMailer).to \
receive(:user_notification).with(user).and_return(mailer)
end
context 'when user is valid' do
let(:user) { FactoryGirl.build(:user) }
it 'calls to send email notifications' do
expect(mailer).to receive(:deliver_now)
user.save
end
end
context 'when user is invalid' do
let(:user) { FactoryGirl.build(:invalid_user) }
it 'does not call to send email notifications' do
expect(mailer).to_not receive(:deliver_now)
user.save
end
end
end
end
def create
@user = User.new(user_params)
if @user.save
NotificationMailer.user_notification(@user).deliver_now
# do other stuff, render, redirect etc
else
# do something else
end
end