编写没有持久存储这么多数据库对象的Rails测试

时间:2013-01-21 17:55:30

标签: ruby-on-rails ruby-on-rails-3 testing rspec rspec2

我正在尝试重构一些RSpec / Rails测试,以便它们尽可能少地保存到数据库中,但是我很难找到如何重写以下测试:

describe User do
  context "record creation" do
    before(:each) { @user = User.new(user_atts) }

    it "should generate a confirmation_token" do
      # Generated as the result of a callback
      @user.save!
      expect(@user.confirmation_token).to be_present
    end

    it "should set the confirmed_at attribute to nil" do
      # Cleared as the result of a callback
      @user.save!
      expect(@user.confirmed_at).to be_nil
    end

    it "should call the send_confirmation_instructions method" do
      @user.should_receive(:send_confirmation_instructions) {}
      @user.save!
    end
  end

  def user_atts
    # return attributes hash
  end
end

这是一个非常简单的例子,但在我的规范中有很多类似的实例,并且,在大多数情况下,它们都将记录保存到数据库中。我很乐意利用RSpec的letsubject帮助者,但我不完全确定这些帮助会在这里有所帮助。

我一直在使用FactoryGirl,并认为它的build_stubbed策略可能会加快我的规格,但我找不到很多可以帮助限制实际记录创建的实例(或者我可能不知道如何使用。)

我认为在某些情况下测试需要记录创建,但上面的示例似乎不像其中之一。我是否应该尝试重构这个或者是否更好地编写这些测试?任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

我的测试可能看起来像这样。

describe User do
  let(:user) { FactoryGirl.build_stubbed(:user) } 

  context "record creation" do
    it "should generate a confirmation_token" do
      user.save!
      expect(user.confirmation_token).to be_present
    end

    it "should set the confirmed_at attribute to nil" do
      user.save!
      expect(user.confirmed_at).to be_nil
    end

    it "should call the send_confirmation_instructions method" do
      expect(user).to receive(:send_confirmation_instructions).once
      user.save!
    end
  end
end

使用Factory Girl创建用户模型。此外,我还有DatabaseCleaner在每次测试后清除数据库,如@RahulGarg所述

您需要做的就是在spec_helper中配置类似这样的内容

  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

这意味着每次测试后数据库都会被清除。