让我们设置模型User
:
class User < ActiveRecord::Base
validate :name, presence: true, uniqueness: { case_sensitive: false }, on: :create
validate :password, presence: true, format: { with: /\A[a-zA-z]*\z/ }
end
看到几种测试方法:
it { expect(user).to validate_presence_of(:name).on(:create) }
或
it do
user = User.create(name: '')
expect(user.errors[:name]).to be_present
end
其他问题:
答案 0 :(得分:1)
应该使用这两个,因为:
it { expect(user).to validate_presence_of(:name).on(:create) }
=&GT;您期望validate_presence_of
应该在create
上运行,这应该是模型的测试用例
it do
user = User.create(name: '')
expect(user.errors[:name]).to be_present
end
=&GT;在使用输入创建用户时,您会产生副作用,因此这应该是控制器的测试用例
为什么你不应该删除其中一个:
删除第一个测试用例:如果您执行数据库验证级别会发生什么,您希望进行有效的记录级别验证
删除第二个测试用例:控制器上发生了什么事实上会创建一个新的User
,您如何期待错误返回!
答案 1 :(得分:1)
以下功能:
errors
被添加到对象中,以便在配置验证时缺少该属性包含在Rails本身的测试中(具体来说,在ActiveModel tests中)。
这需要编写 config 的测试,其中包含您的应用程序的业务逻辑,例如验证特定 {的存在特定 name
课程的{1}}属性等。在我看来,shoulda-matchers gem的匹配者应该为您提供:
User
我认为除非你有你想要测试的错误的特定自定义错误消息(即你已经覆盖了默认的Rails),然后可以删除RSpec.describe User, type: :model do
subject(:user) { build(:user) } # assuming you're using FactoryGirl
describe 'validations' do
specify 'for name' do
expect(user).to validate_presence_of(:name).on(:create)
# NOTE: saving here is needed to test uniqueness amongst users in
# the database
user.save
expect(user).to validate_uniqueness_of(:name)
end
specify 'for password' do
expect(user).to validate_presence_of(:password)
expect(user).to allow_value('abcd').for(:password)
expect(user).to_not allow_value('1234').for(:password)
end
end
end
之类的测试(即使你有自定义错误,我仍然认为它们具有可疑价值,因为如果您将应用程序国际化,这些消息将依赖于区域设置,因此我会测试功能规范中expect(user.errors[:name]).to be_present
上某些错误的显示代替)。
我可以为正则表达式编写这么多测试,但这对于维护来说是很难的。
我认为在测试page
的验证时你不能真正解决这个问题,所以我建议你写一些有代表性的测试用例,然后在发现任何问题时添加/删除这些案例错过了,例如:
format
您认为这个示例中的完整测试覆盖率是多少?
如上所述,在编写单位规格时,我从SimpleCov等报告中获得了100%的代码覆盖率。