【问题标题】:Rspec/FactoryGirl: clean database stateRspec/FactoryGirl:清理数据库状态
【发布时间】:2014-02-14 21:22:07
【问题描述】:

我是 Rspec 和 Factory girl 的新手,我希望我的测试在特定的数据库状态下运行。我知道我可以让工厂女孩创建这些记录,并且在测试运行后对象将被销毁,但是如果我在数据库中有数据会发生什么。

例如:我希望在我通过 Factory Girl 创建的数据库中有 3 条记录时运行测试。但是,我目前在数据库中已经有 1 条模型记录,我不想仅仅为了测试而删除它。将那 1 个模型放在那里会破坏我的测试。

数据库内容

[#<Leaderboard id: 1, score: 500, name: "Trudy">]

leaderboard_spec.rb

require 'spec_helper'

describe Rom::Leaderboard do

    describe "poll leaderboard" do
        it "should say 'Successful Run' when it returns" do
            FactoryGirl.create(:leaderboard, score: 400, name: "Alice")
            FactoryGirl.create(:leaderboard, score: 300, name: "Bob")
            FactoryGirl.create(:leaderboard, score: 200, name: "John")
            Leaderboard.highest_scorer.name.should == "Alice"
        end
    end

end

现在我的测试将失败,因为它会错误地假设 Trudy 是最高得分者,因为测试在错误的状态下运行。

工厂女孩是否提供从数据库中删除记录然后回滚此删除?类似于它如何在数据库中创建记录并回滚

【问题讨论】:

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


    【解决方案1】:

    使用database_cleaner gem 很受欢迎。你可以在这里找到它:

    https://github.com/bmabey/database_cleaner

    文档推荐rspec的配置如下:

    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
    

    这将确保每次测试都有一个干净的数据库。

    【讨论】:

    • 工厂女孩是否提供从数据库中删除记录然后回滚此删除?类似于它如何在数据库中创建记录并回滚
    • 原始问题似乎是在询问如何保持现有记录完好无损。他关于撤消删除的问题是一个想法,但另一种方法可能是完全避免删除。
    【解决方案2】:

    要尽可能直接地回答您的回滚问题:不,没有办法在测试中回滚删除。

    遵循测试约定,您的目标通常是从头开始,并使用 factory_girl 在您需要测试的数据库中高效地构建场景。

    您可以通过例如将 this 添加到您的 leaderboards.rb 工厂文件中来完成您想要的操作:

    factory :trudy do
      id 1
      score 500
      name "Trudy"
    end
    

    或者您可以在测试文件中创建一个简单的辅助函数,以便在需要测试时重新生成该记录:

    def create_trudy
      FactoryGirl.create :leaderboard,
        id: 1,
        score: 500,
        name: "Trudy"
      end
    end
    

    或者您可以将所有这些放在描述块中的 before(:suite) 中,如下所示:

    describe "with a leaderboard record existing" do
      before(:each) do
        FactoryGirl.create :leaderboard, id: 1, score: 500, name: "Trudy"
      end
      # Tests with an initial leaderboard record
    end
    describe "with no leaderboard records initially" do
      # Your test above would go here
    end
    

    在这个最终建议中,您的测试变得非常具有描述性,并且在查看输出时,您将确切地知道您的数据库在每次测试开始时处于什么状态。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多