如何与 rspec 中的许多 "it" 个示例共享变量

How to share a variable with many "it" examples in rspec

我正在使用 let 和 factory girl 创建用户记录。但是我想在上下文中的 2 个测试中使用完全相同的变量,因为 user_id 和电子邮件对我发送的外部 API 很重要。

但是我没有运气制作一个变量来跨示例使用。这是我当前的代码

context "User" do
    let(:user) { FactoryGirl.create(:user) }

    it "should create user and return 'nil'" do
      expect(send_preferences(user, "new")).to eq nil
    end

    it "should not create user preferences again after sending two consecutive same requests" do
      expect(send_preferences(user, "new")).to eq "User preferences already saved. No need to re-save them."
    end

    it "should update user preferences" do
      expect(send_preferences(user, "update")).to eq nil
    end
  end

有什么线索吗?

你可以在 lets 中使用 lets:

context "User" do
  let(:email_address) { 'test@test.com' }
  let(:user) { FactoryGirl.create(:user, email_address: email_address) }

然后您还可以在所有测试中访问 email_address 变量。

之所以可行,是因为以前每次创建用户时工厂都会随机生成电子邮件地址,因为我们没有在任何地方为其设置值。因此,我们在每次测试中都调用了以下代码:

send_preferences(user, "new")

它调用了 'user' let,它创建了一个具有完全随机电子邮件地址的新用户(因为我们没有给它一个特定的电子邮件值)。因此,在后端 API 调用期间,它每次都发送不同的电子邮件地址。

let(:user) { FactoryGirl.create(:user) }

但是,当我们将电子邮件地址 'let' 定义为 'test@test.com',并按照我提供的代码将其传递到用户工厂时,我们用自己的静态覆盖了随机生成的电子邮件地址值,因此,每次我们再次调用代码时:

send_preferences(user, "new") 

它现在触发用户工厂创建,它也采用我们新的 'email_address' let,每次调用时总是设置为 test@test.com 的特定值。

let(:email_address) { 'test@test.com' }
let(:user) { FactoryGirl.create(:user, email_address: email_address) }

因此,当调用后端 API 时,电子邮件地址始终是我们设置的地址。

此外,由于它是一个 let,如果我们愿意,我们可以在任何测试本身中使用该变量。例如:

it 'should set the email address' do
  expect(user.email_address).to eq(email_address)
end

很难用几句话来解释,但如果仍然不清楚,请告诉我。

在我看来,anti-pattern 90% 的时间在多个测试之间共享一个实例化变量。

执行以下操作的问题是您将在数据库中创建对象而不进行清理。

before(:all) do
  @user = FactoryGirl.create :user
end

当然,您可以执行 before(:after) 块或使用 DatabaseCleaner,但我认为测试尽可能独立是更好的做法。在您的情况下,在对第二次发生的事情做出预期之前先设置 send_preferences 事件:

context "User" do
    let(:user) { FactoryGirl.create(:user) }

    # ...

    it "should not create user preferences again after sending two consecutive same requests" do
      send_preferences(user, "new") # Setup
      expect(send_preferences(user, "new")).to eq "User preferences already saved. No need to re-save them."
    end

    it "should update user preferences" do
      send_preferences(user, "new") # Setup
      expect(send_preferences(user, "update")).to eq nil
    end
  end