简体   繁体   English

如何在 Model Rails 中使用条件测试验证

[英]How to test a validation with conditional in a Model Rails

I was wondering if I had to test a model with a particular condidion.我想知道是否必须在特定条件下测试 model。 Let's say that I have a User model who needs a country validation.假设我有一个需要国家/地区验证的用户 model。 This country validations has been set up more than 12 months after the creation of the platform so, we have some User who don't have validate country (or don't have any country)该国家/地区验证已在平台创建后 12 个月以上设置,因此,我们有一些用户没有验证国家/地区(或没有任何国家/地区)

Here's why we have a allow_nil: true .这就是为什么我们有一个allow_nil: true

But we got a problem.但是我们遇到了一个问题。 One of this User, needs to reset his/her password but like the country is not a valid one according, he/she can't reset his/her password.其中一位用户需要重置他/她的密码,但由于该国家/地区不是有效国家/地区,因此他/她无法重置他/她的密码。

So here's what I found to solve this issue:所以这就是我发现解决这个问题的方法:

unless: -> { reset_password_token.present? }

class User < Applicationrecord

VALID_COUNTRY_NAMES = ['Afghanistan', 'Åland', 'Albania', 'Algeria', 'American Samoa', 'Andorra', 'Angola', 'Anguilla', 'Antarctica', 'Antigua and Barbuda'....]

validates :country, allow_nil: true, inclusion: { in: VALID_COUNTRY_NAMES }, unless: -> { reset_password_token.present? }
end

Question: How do I test this specific condition (user with un unvalid country who want to reset password?问题:我如何测试这个特定条件(具有无效国家的用户想要重置密码?

I kind of block on that question and I have to admit that testing is not easy for me.我对这个问题有点犹豫,我不得不承认测试对我来说并不容易。

SOLUTION解决方案

Thanks to @AbM I could resolve it with the following test:感谢@AbM,我可以通过以下测试解决它:

it 'allows existing user to reset password' do
  user = build(:user, country: 'invalid', reset_password_token: 'some_value')
  expect(user.reset_password_token).to eq('some_value')
  expect(user).to be_valid
end

I still don't know why I've struggle so much for a such easy test !我仍然不知道为什么我为一个如此简单的测试而奋斗了这么多!

Don't use the to be_valid matcher.不要使用to be_valid匹配器。 When it fails it tells you nothing about the actual behavior under test.当它失败时,它不会告诉你关于被测实际行为的任何信息。

A real problem is also that you're testing every single validation at once on your model so it really says a lot more about your factories/fixtures then your valiations.一个真正的问题是,您在 model 上一次测试每一个验证,所以它确实比您的验证更多地说明了您的工厂/固定装置。

Instead just setup the model with valid or invalid data (arrange) and call #valid?相反,只需使用有效或无效数据(排列)设置 model 并调用#valid? to trigger the validations (act) and then write expectations based on the ActiveModel::Errors API provided by rails (assert).触发验证(动作),然后根据 rails 提供的ActiveModel::Errors API编写期望(断言)。

context "when the user does not have a password reset token" do
  let(:user) do
    User.new(
      country: 'Lovely'
    )
  end
  it "does not allow an invalid country" do
    user.valid?
    expect(user.errors.details[:country]).to include { error: :inclusion, value: "Lovely" }
  end
end

context "when the user has a password reset token" do
  let(:user) do
    User.new(
      country: 'Lovely',
      reset_password_token: 'abcdefg'
    )
  end

  it "allows an invalid country" do
    user.valid?
    expect(user.errors.details[:country]).to_not include { error: :inclusion, value: "Lovely" }
  end
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM