【问题标题】:Rails app works fine normally, but not in rpsec test. "nil class"Rails 应用程序正常工作,但在 rspec 测试中不行。 “无类”
【发布时间】:2012-08-08 05:42:21
【问题描述】:

创建合同时,它需要一个单位、用户和折扣,并使用这些参数项(模型)来生成发票。

在浏览器中一切正常。但是在运行规范时,我得到undefined method 'value' for nil:NilClass [/app/models/option.rb:19:in 'get_from_database'

Option.rb 的第 18-20 行。这是从数据库中获取站点选项(可由管理员配置)的模型。正常工作(浏览器测试)。

def self.get_from_database(name)
  $option[name] = self.find_by_name(name).send('value')
end

它是从 Contract.rb 调用的:

def start_date=(date)
    self[:start_date] = Date.strptime(date, Option.get_from_database('short_date'))
end

知道为什么我会收到此错误吗?如果我注释掉这一行并重新运行规范测试,我会从另一个类方法调用中得到另一个 nil:NilClass 错误。

我刚刚开始使用 rspec,所以我确定我遗漏了一些东西。注意:第一个测试有效,第二个无效。

require 'spec_helper'

module ContractSpecHelper
  def contract_params
    {  :start_date => "08/09/2012",
       :client_id => '1', 
       :pay_interval_id => '1', 
       :billing_day => "1",
       :prorated => '1',
       :require_next => "1",
       :include_today => "1",
       :unit_id => '45',
       :due => "1" }
  end
end

describe 'Contract' do
  include ContractSpecHelper

  before :each do
    @contract = Contract.new
  end

  describe '#new' do
    it "requires a unit, user, and pay interval id" do
      @contract.should_not be_valid
    end

    it "creates an invoice once saved" do
      @contract.attributes = contract_params
      @contract.save

      @contract.should have(1).invoice
    end
  end

end

【问题讨论】:

  • 也许方法“价值”是通过元编程创建的,它在应用程序中运行良好,因为方法是在应用程序的某个地方创建的,但在 rspec 中它没有发生。所以要测试这个 sn-p 你需要适当地设置环境。
  • 那么我应该include所有相关文件,例如Option.rb、Invoice.rb、Unit.rb等吗?如果是这样,这样做的最佳方法是什么?如果不是,那我应该如何正确设置环境?
  • 显然find_by_name(name) 返回零。这个方法在你的程序中在哪里被调用? name 调用时的值是多少?你的 test 数据库中有这样的对象吗?
  • Option.rb 扩展了 ActiveRecord,所以find_by_name 是通过名称查找记录的基本 ActiveRecord 方法。创建合约时,会执行start_date=(date) 方法(如上所示)。这是调用get_from_database 方法的地方。此外,测试数据库被倾斜和加载。基本上复制了开发数据库。
  • 好的,您的 test 数据库中是否有名称为“short_date”的 Option 对象?如果你运行rails c test 然后Option.find_by_name('short_date'),输出是什么?

标签: ruby-on-rails ruby-on-rails-3 rspec


【解决方案1】:

问题似乎是 Option.find_by_name(name) 返回 nil。

最可能的原因是您没有在测试环境中填充选项表。更改您的代码以处理不存在的选项记录,或在块(等)之前使用 fixtures/factory_girl/machinist/ 在您的测试环境中创建选项记录。

(要回答您的其他问题,您的环境应该加载到您的 spec_helper 中。您不需要手动将 Rails 模型包含到您的 rspec 规范中。)

【讨论】:

  • 有没有办法简单地将数据(不是结构)从 dev 克隆到 test?
  • 一种方法是将您的开发数据库数据转储到db/seeds.db,然后使用rake db:seed RAILS_ENV=test 将数据加载到您的测试环境中。请参阅github.com/rhalff/seed_dump 了解执行此操作的方法。理想情况下,您应该在测试中或通过夹具等创建测试环境数据。您应该期望您的测试环境是易变的。
  • 感谢 cmets!这解决了这个问题,我在这个过程中学到了很多关于 rspec 的知识。我理解您关于将测试数据库留空的评论,现在这很有意义。再次感谢!
猜你喜欢
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
  • 2017-01-24
  • 1970-01-01
  • 2020-11-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多