我想知道是否必须在特定条件下测试模型。假设我有一个需要国家验证的用户模型。该国家/地区验证是在平台创建12个多月后建立的,因此,我们有一些用户没有验证国家/地区(或没有任何国家/地区(
这就是为什么我们有一个allow_nil: true
。
但我们遇到了一个问题。其中一名用户,需要重置他/她的密码,但由于国家不是有效的国家,他/她无法重置他的/她的密码。
以下是我发现的解决这个问题的方法:
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
问题:我该如何测试这个特定条件(拥有未验证国家/地区的用户想要重置密码?
我有点阻止了这个问题,我不得不承认测试对我来说并不容易
解决方案
多亏了@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
我仍然不知道为什么我为了这么简单的考试而如此挣扎!
不要使用to be_valid
匹配器。当它失败时,它"不告诉"你测试中的实际行为。
一个真正的问题是,你要同时在你的模型上测试每一个验证,所以它实际上更多地说明了你的工厂/固定装置,而不是你的验证。
相反,只需使用有效或无效数据设置模型(排列(并调用#valid?
来触发验证(动作(,然后根据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