RSpec抛出NoMethodError,但方法在应用程序中起作用

时间:2016-07-25 14:31:07

标签: ruby-on-rails rspec

我有一种方法' current_balance'在invoice.rb中定义:

class Invoice < ActiveRecord::Base
  belongs_to :purchase
  has_many :payments, dependent: :destroy

  validates :number, presence: true
  validates :currency, format: {with: /\A[A-Z]+\z/, message: "Please enter the 3 letter currency code in CAPS."}
  validates :total_due, presence: true
  validates :due_date, format: {with: /\d{4}-\d{2}-\d{2}/, message: "format must be YYYY-MM-DD"}
  validates :status, presence: true

  def self.next_due
    where("due_date >= ? AND status = ?", Time.now, 'Open').order("due_date DESC").first ? where("due_date >= ?", Time.now).order("due_date DESC").first.due_date : ''
  end

  def self.overdue
    where("due_date < ? AND status = ?", Time.now, 'Open').order("due_date DESC").first ? where("due_date < ?", Time.now).order("due_date DESC").first.due_date : ''
  end

  def current_balance
    self.current_balance = (self.total_due - self.payments.sum(:amount_paid))
  end

  def status
    if self.current_balance > 0
      then self.status = "Open"
    elsif self.current_balance < 0
      then self.status = "Overpaid"
    elsif self.current_balance = 0
      then self.status = "Paid"
    end
  end
end

工厂,发票.rb

FactoryGirl.define do
  factory :invoice do
    sequence(:id) { |number| number }
    sequence(:purchase_id) { |n| n }
    number { FFaker::String.from_regexp(/\A[A-Za-z0-9]+\z/) }
    terms { FFaker::String.from_regexp(/\A[A-Za-z0-9\s]+\z/) }
    currency { FFaker::String.from_regexp(/\A[A-Z]+\z/) }
    total_due {'200.00'}
    due_date { FFaker::Time.date }
    notes { FFaker::HipsterIpsum.paragraph }
    status {[:open, :paid, :canceled].sample}
  end

  factory :invalid_invoice, parent: :invoice do
    currency nil
  end
end

模型规范,invoices_spec.rb包含:

require "spec_helper"

describe Invoice, '#current_balance' do
  it "calculates the current balance of an invoice" do
    invoice = FactoryGirl.create(:invoice, total_due: 200)
    invoice.payments << FactoryGirl.create(:payment, amount_paid: 100)
    invoice.payments << FactoryGirl.create(:payment, amount_paid: 50)
    expect(invoice.current_balance).to eq(50)
  end
end

describe Invoice do
  before(:all) { @invoice = FactoryGirl.build(:invoice) }
    it "has a valid factory" do
      expect(FactoryGirl.create(:invoice)).to be_valid
    end

    it "is invalid without a number" do
      invoice = Invoice.new(number: nil)
      expect(invoice).to_not be_valid
    end

    it "is invalid without a currency" do
      invoice = Invoice.new(currency: nil)
      expect(invoice).to_not be_valid
    end

    it "is invalid without a total_due" do
      invoice = Invoice.new(total_due: nil)
      expect(invoice).to_not be_valid
    end

    it "is invalid without a due_date" do
      invoice = Invoice.new(due_date: nil)
      expect(invoice).to_not be_valid
    end

    it "is invalid without a status" do
      invoice = Invoice.new(status: nil)
      expect(invoice).to_not be_valid
    end

end

该方法运行良好,并在运行应用程序时计算发票的当前余额。但是,当我运行模型规范时,我收到错误。

#current_balance&#39; &安培; &#39;它有一个有效的工厂&#39;示例通过,其余的都失败并出现相同的错误。

Failure/Error: expect(invoice).to_not be_valid
NoMethodError:
 undefined method `-' for nil:NilClass

我做错了什么?

1 个答案:

答案 0 :(得分:0)

啊,对于完整的型号代码,问题非常清楚。这一切都从这一行开始:

validates :status, presence: true

触发status的getter,触发current_balance的getter,通过从self.current_balance中减去未设置的内容(total_due)来设置nil在所有那些失败的测试用例中。因此错误信息。