使用相同代码的2个测试之间的Rspec结果不一致

时间:2018-07-19 17:32:50

标签: ruby-on-rails testing rspec

我有一个模型规范,该规范抛出意外错误(没有正确构建对象)。 当我将相同的代码移至先前的测试中时,它运行平稳。

这是有问题的期望:

expect(title.full_title.length).to be <= 140

将行添加到第一个测试时,它通过了,而第二个测试失败了:

  describe "generates a title" do
    let(:collection) { FactoryBot.create(:collection) }
    let(:items) { FactoryBot.create_list(:item, 10, collection: collection, chosen: true) }
    let(:title) { Title.create_title(collection) }

context "happy path" do
  it "assigns keywords by score" do
    array = []
    items.each do |i|
      array << [i.search.term, i.search.score]
    end
    array.sort! { |a, b| a[1] <=> b[1] }
    split_title = title.full_title.split(', ')
    remaining_chars = 140
    i = 0

    split_title.each do |s|
      if remaining_chars - s.length >= 0
        expect(s).to eq(array[i][0])
        i +=  1
        remaining_chars -= s.length
      end

      expect(title.full_title.length).to be <= 140
    end
  end

  it "does not exceed 140 characters" do
    expect(title.full_title.length).to be <= 140
  end
end

这是错误消息,它不会创建对象:

  1) Title generates a title happy path does not exceed 140 characters
     Failure/Error: remaining_chars = 140 - keywords[0].length

     NoMethodError:
       undefined method `length' for nil:NilClass

TIA!

1 个答案:

答案 0 :(得分:1)

这是一个远景,但如果我今天很幸运,请尝试。

猜猜:Title.full_title的实现(您没有分享)在某种程度上取决于与用于初始化Item对象的集合相关的Title的存在。

如果该假设正确,则let的惰性会导致不同的行为。

在第一个it中,您实际上调用了items(例如items.each),因此对let(:items)进行了评估,在DB中创建了行,并title.full_title不返回nil

有几种可能的解决方法:

  1. 改进full_title的实现以始终返回字符串。
  2. 在第二种情况下,请致电items

it "does not exceed 140 characters" do items expect(title.full_title.length).to be <= 140 end

  1. 使用let!(:items),它会立即进行评估(不是惰性的)