为什么未在 rails rspec 模型规范中设置主题的此属性?

Why is this attibute on a subject not being set in a rails rspec model spec?

我有一个测试模型的规范,如下所示:

RSpec.describe SomeModel, type: :model do

  subject { described_class.new(test_amount: 99) }

  describe 'validates a column' do
    it 'does some validations' do
      expect(subject).to validate_presence_of(:test_amount)
    end
  end
end

还有一个看起来像这样的模型:

class SomeModel < ApplicationRecord
  validates :test_amount, presence: true
end

在模式中,它的列看起来像这样,带有一个非空集:

t.integer "test_amount", default: 0, null: false

无论我做什么或将代码放在哪里,test_amount 在测试和错误时始终为 nil。 我试过移动测试线,将主题放在之前等等,但总是 数据库抛出非空错误,即使我在模型代码中提出 test_amount 值不是 99,而是 nil。如果我提高测试值 之前是这样的:

before do
  raise subject.test_amount
end

这确实会导致 99,但是如果我删除它,它始终为 nil 并在它到达测试的预期部分时抛出错误。

为了使该测试正常运行,我缺少什么,在实际测试步骤中进行测试时,我似乎无法将 test_amount 设置为 99。

测试总是抛出错误:

PG::NotNullViolation: ERROR: null value in column "test_amount" of relation "some_models" violates not-null constraint 或类似的,但我在验证前检查了 test_amount 的值,但没有设置。

感谢您的帮助,我觉得这里缺少一些非常基本的东西。

您可以使用如下 valid? and errors 方法为 presence 验证编写测试用例:

RSpec.describe SomeModel, type: :model do

  subject { described_class.new(test_amount: test_amount) }

  describe 'validates a column' do
    context 'when valid test_amount'
      let(:test_amount) { 99 }
      it 'does not throw error' do
        expect(subject.valid?).to eq(true)
        expect(subject.errors[:test_amount].size).to eq(0)
      end
    end

    context 'when invalid test_amount'
      let(:test_amount) { nil }
      it 'throws error' do
        expect(subject.valid?).to eq(false)
        expect(subject.errors[:test_amount].size).to eq(1)
      end
    end
  end
end

这是否有可能是因为未在测试环境中 运行 迁移?

bundle exec rake db:prepare RAILS_ENV=test

# or for rack applications

bundle exec rake db:prepare RACK_ENV=test

除此之外,我认为是因为我们没有将记录保存到数据库中。我们不希望验证是 运行.

根据 this documentation,我们只希望在调用 Record#saveRecord#save! 时进行 运行 验证。

当 运行 宁 Record#new 我们正在创建一个新实例但 没有保存 到我们的数据库。

Using the new method, an object can be instantiated without being saved:

当运行宁Record#create我们初始化记录然后通过调用Record#save.

将其保存到数据库

首先验证-

  1. 记录已保存。
  2. 一旦持久化,然后检查属性值。

此外,尝试将此行移动到 describe 块内 -

 subject { described_class.new(test_amount: 99) }