为什么这个Rspec测试返回"已经发送电子邮件"

Mar*_*tin 4 rspec ruby-on-rails factory-bot

这是我的spec文件,当为上下文添加测试"而不是可单独更新用户余额"时,我得到以下错误.

require 'spec_helper'

describe Sale do 

  context 'after_commit' do

    context 'assignable' do 
      sale = FactoryGirl.create(:sale, earned_cents: 10, assignable: true)
      after { sale.run_callbacks(:commit) }

      it 'updates user balance' do
        sale.user.balance.should == sale.earned
      end
    end

    context 'not assignable' do 
      sale = FactoryGirl.create(:sale, earned_cents: 10, assignable: false)
      after { sale.run_callbacks(:commit) }

      it 'does not updates user balance' do
        sale.user.balance.should_not == sale.earned
      end
    end

  end 
end
Run Code Online (Sandbox Code Playgroud)

和工厂

require 'faker'

FactoryGirl.define do
  factory :user do
    email Faker::Internet.email
    password "mypassword"
  end

FactoryGirl.define do
  factory :sale do
    earned_cents 5
    user
  end
end
Run Code Online (Sandbox Code Playgroud)

/spec/spec_helper.rb我也有过这样

require 'database_cleaner'
RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end
end
Run Code Online (Sandbox Code Playgroud)

这就是我得到的错误.

`save!': Validation failed: Email has already been taken (ActiveRecord::RecordInvalid)

我猜它与Factory user内部的引用有关Sale,但我不知道为什么它没有为第二次测试生成新用户或从数据库中删除它.任何的想法?

Gla*_*eep 15

在您的用户工厂中,请尝试以下方法:

factory :user do
  email { Faker::Internet.email }
  password "mypassword"
end
Run Code Online (Sandbox Code Playgroud)

为什么你必须在卷曲括号中包含:避免缓存值

factory(:user)块被定义出厂的时候每次创建一个创纪录的时间运行,而不是.因此,如果第一次Factory::Internet.email评估foo@bar.com,那么工厂将尝试使用相同的电子邮件创建所有后续用户!)(根据@kristinalim,编辑语法)

  • 是.定义工厂时运行`factory(:user)`块,而不是每次创建记录时都运行.因此,如果`Factory :: Internet.email`第一次评估为"foo@bar.com",那么做`email Faker :: Internet.email`就像在做'email'foo @ bar.com'. (7认同)
  • 形成块的大括号使得这种电子邮件生成方法能够在这种情况下重新运行多次. (3认同)