优雅的方式来测试创建新对象

时间:2017-04-13 01:01:10

标签: ruby-on-rails rspec rspec-rails

我正在构建一个非常基本的测试,以检查是否在关系中创建了一个对象。 Website has_many languages。我有方法add_language接收一组id并添加它们。

这是我的一些测试:

  describe '#add_languages' do
    subject{ build(:website) }

    it 'return nil if no language is added' do
      expect(subject.add_languages []).to be_nil
    end
    it 'adds one single language' do
      languages_ids = [Language.last.id]
      original_count = subject.languages.count
      subject.add_languages languages_ids
      expect(subject.languages.count).to eq(original_count + languages_ids.count)
    end
    it 'adds multiple languages' do
      languages_ids = Language.limit(3).pluck :id
      original_count = subject.languages.count
      subject.add_languages languages_ids
      expect(subject.languages.count).to eq(original_count + languages_ids.count)
    end
 end

我不喜欢的是

1)代码重复 2)我不喜欢使用eq,但不知道如何使用其他匹配器

编写这些测试的优雅方法是什么?

2 个答案:

答案 0 :(得分:0)

您可以通过两种快速方法:添加辅助方法或添加循环。

帮助方法

it "adds on single language" do
  check_creates_languages([Language.last.id])
end

it "Adds multiple languages" do
  check_creates_languages(...)
end

def check_creates_languages(language_ids)
  original_count = ... # etc
end

<强>循环

[1,3].each do |language_count|
  it "can add #{language_count} language(s)" do
    original_count = Language.last(language_count).count
    # etc
  end
end

此外,使用eq并没有错,这就是它的用途。你还想用什么?您也可以使用be

https://github.com/rspec/rspec-expectations

答案 1 :(得分:0)

您可以这样做:

expect{subject.add_languages languages_ids}.to change{Language.count}.by(1)

或多或少(根据您的使用案例)。