我刚开始测试Rails,所以这可能是一件很小的事情,但是我不知道出了什么问题。因此,我想测试一些模型。现在测试很简单。测试属性的存在并保存是否满足所有验证条件。
我的一个模型Profile
belongs_to
我的Users
模型和passes所有这些测试spec/models/profiles_spec.rb
:
require 'rails_helper'
RSpec.describe Profile, type: :model do
context 'validation tests' do
it 'ensures user_id presence' do
profile = Profile.new(platform: 0, region: 0, tag: 'GamerTag', sr: 1600).save
expect(profile).to eq(false)
end
it 'ensures platform presence' do
profile = Profile.new(user_id: 1, region: 0, tag: 'GamerTag', sr: 1600).save
expect(profile).to eq(false)
end
it 'ensures region presence' do
profile = Profile.new(user_id: 1, platform: 0, tag: 'GamerTag', sr: 1600).save
expect(profile).to eq(false)
end
it 'ensures tag presence' do
profile = Profile.new(user_id: 1, platform: 0, region: 0, sr: 1600).save
expect(profile).to eq(false)
end
it 'ensures sr presence' do
profile = Profile.new(user_id: 1, platform: 0, region: 0, tag: 'GamerTag').save
expect(profile).to eq(false)
end
it 'should save successfully' do
profile = Profile.new(user_id: 1, platform: 0, region: 0, tag: 'GamerTag', sr: 1600).save
expect(profile).to eq(true)
end
end
end
app/models/profile.rb
:
class Profile < ApplicationRecord
validates :platform, presence: true
validates :region, presence: true
validates :tag, presence: true
validates :sr, presence:true
belongs_to :user
enum platform: [:pc, :xbl, :psn]
enum region: [:us, :eu]
end
但是,还有其他模型,它们“通过”了所有属性存在验证测试,那里有些问题,因为当我注释掉其属性验证并通过'should save successfully'
测试时,它们仍然通过。
最令人困惑的部分?当我运行rails控制台并进行手动测试时,它会返回期望值(true),就像我的Student
模型中的belongs_to :profile
一样。
所以我真的不知道这是怎么回事。任何想法请把它们扔掉。如果您还需要更多信息,请告诉我。
答案 0 :(得分:1)
确实,这是缺少相关记录的错误。让我们以教练规范为例:
it 'should save successfully' do
coach = Coach.new(profile_id: 1, roles: ['tank']).save
expect(coach).to eq(true)
end
(在我的实验中)这里没有ID为1的个人资料。实际上,根本没有配置文件。因此,此规范失败了,正如预期的那样。
Buuuut,等我们到达个人资料规范时
it 'should save successfully' do
profile = Profile.new(user_id: 1, platform: 0, region: 0, tag: 'GamerTag', sr: 1600)
expect(profile).to eq(true)
end
id = 1的用户存在(可能是因为用户规范在此规范之前运行并成功创建了用户记录)。
学习的经验:
答案 1 :(得分:0)
首先,您正在以一种非常低效的方式编写测试。如果您不想测试验证,则无需测试save
方法的返回值,而只需测试valid?
方法的值和errors
哈希。
RSpec.describe Profile, type: :model do
context 'validation tests' do
it 'ensures user_id presence' do
profile = Profile.new(platform: 0, region: 0, tag: 'GamerTag', sr: 1600, user_id: nil) #you should be explicit with the user_id value being nil, tests should be explicit, it may seem unnecesary but it makes them easier to read
expect(profile).to be_invalid #or expect(profile).not_to be_valid
expect(profile.errors[:user_id]).to be_present #you could test the actual message too, not just the presence on any error
end
end
end
该测试实际上仅测试验证,并且还确保user_id
字段中存在错误。
通过实际测试,您无法知道实际上是什么导致对象无法保存。它可以是任何东西:另一个验证,返回false的before_save回调,在插入数据库时的无效值等等。由于它必须将记录实际写到数据库上,因此它也比较慢,测试valid?
是在内存上完成的,这要快得多。
Id'建议您阅读有关FactoryBot的信息,因此您不必在每次测试中都重复Profile.new....
。
如果您仍想在上次测试中测试save
的返回值,则必须知道为什么它没有被保存,您可以使用save!
引发一个异常,而不是返回false调试代码,然后您还可以检查profile.errors.full_messages
来查看是否存在设置测试时没有考虑的错误。