RSpec - 测试共享相同验证的2个属性的错误

时间:2014-10-09 15:46:27

标签: ruby-on-rails rspec

我的模型中有两个共享相同验证的属性

validates :first_name, :last_name, length: {minimum: 2}

现在我测试:first_name属性如下:

RSpec.describe User, :type => :model do
  it 'is invalid if the first name is less than two characters'
    user = User.create(
      first_name: 'a'
    )
  expect(user).to have(1).errors_on(:first_name)
end

为了不熟悉我如何设置模型的开发人员,我想明确说明这两个属性'与这样的事情的关系:

it 'is invalid if the first name and/or last name has less than two characters'
  user = User.create(
    first_name: 'a',
    last_name: 'b
  )
  expect(user).to have(1).errors_on(:first_name, :last_name)

显然这会引发错误:

  

错误的参数数量(2为0..1)

如果我进行了两次验证,那么同样适用:

validates :first_name, :last_name, length: {minimum: 2}, format: {with: /^([^\d\W]|[-])*$/}

尝试测试2个错误:

it 'is invalid if the first name and/or last name has less than two characters and has special characters'
  user = User.create(
    first_name: '@',
    last_name: '#
  )
  expect(user).to have(2).errors_on(:first_name, :last_name)

2 个答案:

答案 0 :(得分:1)

在RSpec 3.x中,您可以将期望与.and

结合起来
it 'is invalid if the first name and/or last name has less than two characters' do
  user = User.create(first_name: 'a', last_name: 'b')
  expect(user).to have(1).errors_on(:first_name).and have(1).errors_on(:last_name)
end

查看rspec-expectations文档了解详情。

对于RSpec 2.x,您需要执行以下操作之一:

it 'is invalid if the first name and/or last name has less than two characters' do
  user = User.create(first_name: 'a', last_name: 'b')
  expect(user).to have(1).errors_on(:first_name) && have(1).errors_on(:last_name)
end

# or
it 'is invalid if the first name and/or last name has less than two characters' do
  user = User.create(first_name: 'a', last_name: 'b')
  expect(user).to have(1).errors_on(:first_name)
  expect(user).to have(1).errors_on(:last_name)
end

它不是很漂亮,但应该有用。

修改

OP正在使用rspec-collection_matchers gem。该gem的自定义匹配器不包含RSpec 3 mixin模块RSpec::Matchers::Composable,因此#and方法无法识别。

要绕过这个问题,有几件事要做。最简单的方法是使用上面的&&技术(在我的RSpec 2.x建议中)。要使用 RSpec 3匹配器,您需要使用be_valid

it 'is invalid if the first name and/or last name has less than two characters' do
  user = User.create(first_name: 'a', last_name: 'b')
  expect(user).to_not be_valid
end

当然,这并不像原先预期的那样区分first_name错误和last_name错误。要使用be_valid匹配器执行此操作,您必须将测试分为两个测试:

it 'is invalid if the first name has less than two characters' do
  user = User.create(first_name: 'a', last_name: 'abc')
  expect(user).to_not be_valid
end

it 'is invalid if the last name has less than two characters' do
  user = User.create(first_name: 'abc', last_name: 'a')
  expect(user).to_not be_valid
end

答案 1 :(得分:0)

您的测试应如下所示:

it 'invalid length' do
  user = User.new(first_name: '@', last_name: '#')
  user.valid?
  expect(user.errors.count).to eq 2
  expect(user.errors[:first_name]).to include "is too short (minimum is 2 characters)"
  expect(user.errors[:last_name]).to include "is too short (minimum is 2 characters)"
end

user.valid?调用将针对将填充错误的验证运行新用户。

进行单元测试这是一个非常详细的测试 - 我强烈推荐shoulda matchers。您只需两行即可测试上述内容:

it { is_expected.to ensure_length_of(:first_name).is_at_least(2) }
it { is_expected.to ensure_length_of(:last_name).is_at_least(2) }