如何使用 RSpec 测试 Rails 中的包含验证

发布于 2024-12-04 15:59:12 字数 998 浏览 2 评论 0原文

我的 ActiveRecord 中有以下验证。

validates :active, :inclusion => {:in => ['Y', 'N']}

我正在使用以下内容来测试我的模型验证。

should_not allow_value('A').for(:active)
should allow_value('Y').for(:active)
should allow_value('N').for(:active)

有没有更干净、更彻底的测试方法?我目前正在使用 RSpec2 和 Shoulda 匹配器。

编辑

环顾四周后,我发现,这可能是一种“好的”测试方法,应该不为此提供任何内容,任何需要它的人都可以为其编写自己的自定义匹配器。(并且可能会将其贡献回项目)。一些可能有趣的讨论链接:

  • 指向上述内容的链接。 链接 1 , <一href="http://groups.google.com/group/shoulda/browse_thread/thread/84aa287d36c4e512/036ccffce9aa10b5?lnk=gst&q=validates_inclusion_of#036ccffce9aa10b5%20This%20one%20is%20more" rel="noreferrer">链接2

  • should_ensure_value_in_range 这个接近于可以使用的内容,但只接受范围而不是值列表。自定义匹配器可以基于此。

I have the following validation in my ActiveRecord.

validates :active, :inclusion => {:in => ['Y', 'N']}

I am using the following to test my model validations.

should_not allow_value('A').for(:active)
should allow_value('Y').for(:active)
should allow_value('N').for(:active)

Is there a cleaner and more through way of testing this? I am currently using RSpec2 and shoulda matchers.

EDIT

After some looking around I only found, this probably an 'ok' way of testing this, shoulda does not provide anything for this and anyone who requires it can write their own custom matcher for it.(And probably contribute it back to the project). Some links to discussions that might be intresting:

  • Links which indicate to the above . Link 1 , Link 2

  • should_ensure_value_in_range This one comes close to what can be used, but only accepts ranges and not a list of values. Custom matcher can be based on this.

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

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

发布评论

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

评论(4

眼眸里的那抹悲凉 2024-12-11 15:59:12

使用 shoulda_matchers

shoulda-matchers 的最新版本(至少从 v2.7.0 开始),您可以执行以下操作:

expect(subject).to validate_inclusion_of(:active).in_array(%w[Y N])

这测试验证中可接受值的数组是否与此规范完全匹配。

在早期版本中, >= v1.4 , shoulda_matchers 支持以下语法:

it {should ensure_inclusion_of(:active).in_array(%w[Y N]) }

Use shoulda_matchers

In recent versions of shoulda-matchers (at least as of v2.7.0), you can do:

expect(subject).to validate_inclusion_of(:active).in_array(%w[Y N])

This tests that the array of acceptable values in the validation exactly matches this spec.

In earlier versions, >= v1.4 , shoulda_matchers supports this syntax:

it {should ensure_inclusion_of(:active).in_array(%w[Y N]) }
饮湿 2024-12-11 15:59:12

如果您要测试的元素多于布尔值 Y/N,那么您也可以尝试。

it "should allow valid values" do
  %w(item1 item2 item3 item4).each do |v|
    should allow_value(v).for(:field)
  end
end
it { should_not allow_value("other").for(:role) }

您还可以将 %w() 替换为您在模型中定义的常量,以便测试是否仅允许使用常量值。

CONSTANT = %w[item1 item2 item3 item4]
validates :field, :inclusion => CONSTANT

然后测试:

it "should allow valid values" do
  Model::CONSTANT.each do |v|
    should allow_value(v).for(:field)
  end
end

If you have more elements to test than a boolean Y/N then you could also try.

it "should allow valid values" do
  %w(item1 item2 item3 item4).each do |v|
    should allow_value(v).for(:field)
  end
end
it { should_not allow_value("other").for(:role) }

You can also replace the %w() with a constant you have defined in your model so that it tests that only the constant values are allowed.

CONSTANT = %w[item1 item2 item3 item4]
validates :field, :inclusion => CONSTANT

Then the test:

it "should allow valid values" do
  Model::CONSTANT.each do |v|
    should allow_value(v).for(:field)
  end
end
月隐月明月朦胧 2024-12-11 15:59:12

我发现一个自定义的 shoulda 匹配器(在我正在从事的项目之一中)尝试接近测试如下所示的内容:

示例:

it { should validate_inclusion_check_constraint_on :status, :allowed_values => %w(Open Resolved Closed) }
it { should validate_inclusion_check_constraint_on :age, :allowed_values => 0..100 }

匹配器尝试确保存在一个数据库约束,该约束在尝试保存时会爆炸.我将尝试给出这个想法的本质。比赛?实现的作用类似于:

  begin
    @allowed_values.each do |value|
      @subject.send("#{@attribute}=", value)
      @subject.save(:validate => false)
    end
  rescue ::ActiveRecord::StatementInvalid => e
    # Returns false if the exception message contains a string matching the error throw by SQL db
  end

我想如果我们稍微改变上面的内容,说 @subject.save 并让 Rails 验证爆炸,当异常字符串包含与真正的异常错误匹配的内容时,我们可以返回 false信息。

我知道这对于为项目做出贡献还远非完美,但我想如果您确实想测试大量 :inclusion 验证。

I found one custom shoulda matcher (in one of the projects I was working on) which attempts to coming close to test something like this:

Examples:

it { should validate_inclusion_check_constraint_on :status, :allowed_values => %w(Open Resolved Closed) }
it { should validate_inclusion_check_constraint_on :age, :allowed_values => 0..100 }

The matcher tries to ensure that there is a DB constraint which blows up when it tries to save it.I will attempt to give the essence of the idea. The matches? implementation does something like:

  begin
    @allowed_values.each do |value|
      @subject.send("#{@attribute}=", value)
      @subject.save(:validate => false)
    end
  rescue ::ActiveRecord::StatementInvalid => e
    # Returns false if the exception message contains a string matching the error throw by SQL db
  end

I guess if we slightly change the above to say @subject.save and let Rails validation blow up, we can return false when the exception string contains something which close matches the real exception error message.

I know this is far from perfect to contributed back to the project, but I guess might not be a bad idea to add into your project as a custom matcher if you really want to test a lot of the :inclusion validation.

蓬勃野心 2024-12-11 15:59:12

在 shoulda-matchers >= 5 中,您应该能够使用 :validate_inclusion_of

it { should validate_inclusion_of(:active).in_array(%w[Y N]) }

In shoulda-matchers >= 5 you should be able to use :validate_inclusion_of as

it { should validate_inclusion_of(:active).in_array(%w[Y N]) }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文