在Application Mailer(Rails,RSpec,FactoryGirl)中询问模型的属性值时出现NoMethodError

时间:2016-01-07 13:32:46

标签: ruby-on-rails rspec

我正在尝试使用RSpecFactoryGirl测试一个非常基本的示例。我已经构建了一个GlobalSetting模型来保存我的变量并动态更改它们,因此它包含(:id, :name, :val),这很明显。

不幸的是,最简单的例子失败了:

/app/mailers/application_mailer.rb:3:in `<class:ApplicationMailer>': undefined method `val' for nil:NilClass (NoMethodError)

我怀疑在被application_mailer调用之前,FactoryGirl元素没有持久化到数据库。

application_mailer.rb

class ApplicationMailer < ActionMailer::Base

  default_from_email = GlobalSetting.find_by(name: "DEFAULT_FROM_EMAIL").val

  default from: default_from_email
  layout 'mailer'

end

application_mailer_spec.rb

require "rails_helper"

RSpec.describe ApplicationMailer, type: :mailer do
  let!(:default_from_email) { FactoryGirl.create(:default_from_email)}
  let!(:ol_internal_dl) { FactoryGirl.create(:ol_internal_dl)}

  before(:each) do
    ActionMailer::Base.delivery_method = :test
    ActionMailer::Base.perform_deliveries = true
    ActionMailer::Base.deliveries = []
  end

  it 'should send an email' do
    pending
  end
end

global_settings.rb (FactoryGirl)

# == Schema Information
#
# Table name: global_settings
#
#  id         :integer          not null, primary key
#  name       :string
#  val        :string
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

FactoryGirl.define do

  factory :ol_internal_dl do
    name "OL_INTERNAL_DL"
    val "internal@email.com"
  end

  factory :default_from_email do
    name "DEFAULT_FROM_EMAIL"
    val "default@email.com"
  end

end

我如何“通过测试”?

1 个答案:

答案 0 :(得分:1)

我认为问题在于您的FactoryGirl定义。默认情况下,FactoryGirl使用工厂名称来猜测&#34;猜测&#34;关联的类名。在你的情况下,你打电话给工厂:default_from_email,但我猜你没有这个名字的课程?

尝试将class: GlobalSetting添加到工厂定义中,如下所示:

factory :default_from_email, class: GlobalSetting do
    name "DEFAULT_FROM_EMAIL"
    val "default@email.com"
end

来自FactoryGirl documentation

# This will guess the User class
FactoryGirl.define do
  factory :user do
    first_name "John"
    last_name  "Doe"
    admin false
  end

  # This will use the User class (Admin would have been guessed)
  factory :admin, class: User do
    first_name "Admin"
    last_name  "User"
    admin      true
  end
end

更新:根据您的评论,仔细查看您的代码后,问题似乎是您在班级default_from_email中设置了一个局部变量。当您的测试中此类为require时,它会尝试调用#find_by,因为您在数据库中没有该记录,所以在任何事情都无法执行之前,您的测试都会失败。一些可能的解决方案:

  1. 将您的#find_by更改为find_or_create
  2. 在运行测试之前对数据库进行种子设定,并require - 运行ApplicationMailer,然后记录应该存在,您将看不到nil错误。