为什么对不在Rails RSPEC模型规范中设置的主题上的此算法?

发布于 2025-01-17 19:25:26 字数 1082 浏览 2 评论 0原文

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

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 都是测试和错误时始终为零。 我尝试过移动测试线,将主题放在前面等等,但总是 数据库抛出非空错误,即使我在模型代码中提出 test_amount 值不是 99,而是 nil。如果我提高测试值 a before 像这样:

before do
  raise subject.test_amount
end

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

为了让这个测试正常工作,我缺少什么,在实际测试步骤中进行测试时,我似乎无法将 test_amount 设置为 99。

测试总是抛出错误:

PG::NotNullViolation: ERROR: null value in column "test_amount" of relation "some_models"违反了非空约束或类似的,但在验证之前要检查test_mount 的值,但未设置。

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

I have a spec testing a model that looks like this:

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

And a model that looks like this:

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

And in the schema it's column looks like this with a not-null set:

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

No matter what I do or where I put the code, test_amount is always nil when being tests and errors.
I've tried moving the test lines around, putting the subject in a before etc, but always the
database is throwing a non-null error and even if I raise in the model code
the test_amount value is not 99 it is nil. If I raise the test value in
a before like this:

before do
  raise subject.test_amount
end

That does result in a 99, however if I remove this, it is always nil and throws an error when it gets to the expect part of the test.

What am I missing in order to get this test to work, I just cannot seem to get the test_amount to set to 99 when being tested in the actual test step.

The test always throws the error:

PG::NotNullViolation: ERROR: null value in column "test_amount" of relation "some_models" violates not-null constraint or similar, I have but in before-validations to check the value of test_amount and it does not get set.

Thanks for you help, I feel like there's something really basic I'm missing here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

树深时见影 2025-01-24 19:25:26

首先,验证 -

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

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

 subject { described_class.new(test_amount: 99) }

First of all, verify that -

  1. The record is persisted.
  2. Once persisted, then check the attribute value.

Moreover, try moving this line inside the describe block -

 subject { described_class.new(test_amount: 99) }
﹏雨一样淡蓝的深情 2025-01-24 19:25:26

这有可能是由于未在测试环境中运行迁移吗?

bundle exec rake db:prepare RAILS_ENV=test

# or for rack applications

bundle exec rake db:prepare RACK_ENV=test

除此之外,我认为,因为我们不是保存记录数据库。我们不会期望验证会进行。

此文档记录#保存!已被调用。

运行记录#新时,我们正在创建一个新实例,但不保存到我们的数据库中。

使用新方法,可以在不保存的情况下实例化对象:

When running Record#create 我们初始化记录,然后通过调用record#save将其保存到数据库中。

Any chance this is due to not running migrations in the test environment?

bundle exec rake db:prepare RAILS_ENV=test

# or for rack applications

bundle exec rake db:prepare RACK_ENV=test

Other than this I would think that because we aren't saving the record to the database. We wouldn't expect validations to be ran.

As per this documentation we are only expecting to run validations when Record#save or Record#save! has been called.

When running Record#new we are creating a new instance but not saving to our database.

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

When running Record#create we initialize the record and then save this to the database by calling Record#save.

恏ㄋ傷疤忘ㄋ疼 2025-01-24 19:25:26

您可以用有效吗? /a> anderrors> errors> errors 类似下面的方法:

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

You can write test cases for the presence validation with valid? and errors methods like below:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文