rspec模型规格让vs工厂

时间:2016-04-13 15:02:56

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

我刚开始接受测试,而且我应该使用let时并不完全清楚。

我是否应该在以下模型测试中使用let进行延迟加载,或者由于每次测试中的数据都有所不同,我可以保持原样吗?正如我在一些例子中看到的那样,对于控制器测试来说更为重要,因为:task对于每个动作测试都是相同的。

模型规范

require 'rails_helper'

RSpec.describe Task, type: :model do

  describe "model validations" do

    it "has a valid factory" do
      expect(build(:task)).to be_valid
    end

    it "is invalid without executor" do
      expect(build(:task, executor_id: nil)).not_to be_valid
    end

    it "is invalid without assigner" do
      expect(build(:task, assigner_id: nil)).not_to be_valid
    end

    it "is invalid without content" do
      expect(build(:task, content: nil)).not_to be_valid
    end

    it "is invalid without deadline" do
      expect(build(:task, deadline: nil)).not_to be_valid
    end

    it "is invalid with deadline in the past" do
      expect(build(:task, deadline:  Faker::Time.between(DateTime.now - 1, DateTime.now - 2))).not_to be_valid
    end
  end
end

工厂

FactoryGirl.define do
  factory :task do
    content { Faker::Lorem.sentence }
    deadline { Faker::Time.between(DateTime.now + 2, DateTime.now + 3) }
    association :executor, factory: :user
    association :assigner, factory: :user
  end
end

2 个答案:

答案 0 :(得分:1)

我建议你保留它的方式而不是使用let。不要担心干扰你的测试。它们不会相互交互,因此您不会遇到应用程序逻辑中的代码重复问题。

对于它的价值,你可以使用shoulda-matchers gem来完成你所拥有的:https://github.com/thoughtbot/shoulda-matchers

describe Task do
  describe "validations" do
    it { is_expected.to validate_presence_of(:content) }
    it { is_expected.to validate_presence_of(:deadline) }
  end
end

答案 1 :(得分:1)

let的好处来自您上面使用的表单中没有的测试。想象一下这个群体:

context "completing tasks" do
  let(:completing_a_task){ task.complete }
  context "that aren't due yet" do
    let(:task){ create(:not_due_task) }
    it "should not send an email" do
       expect( TaskMailer ).not_to receive(:deliver_message)
       expect{ completing_a_task }.not_to raise_error
    end
  end
  context "overdue" do
    let(:task){ create(:overdue_task) }
    it "should send an email" do
       expect( TaskMailer ).to receive(:deliver_message)
       expect{ completing_a_task }.not_to raise_error
    end
  end
end

通过允许后期绑定,您可以进行最小的更改,但提供最大的覆盖率。为了设置测试所需的适当行为,您需要的协作者越多,您就越有可能从let中受益。虽然您尝试在测试套件中特别需要驾驶DRY,但测试的巨大设置块是一种气味,let技术是帮助战斗的好工具为了清晰和简单,即使您的域名存在复杂性。我自己的例子还没有包括合作者,但希望这个概念仍然足够清晰。