2

database_cleaner 在大多数情况下都有效,但在某些情况下,我希望在每次测试后清除 user_id 之类的东西,但事实并非如此。因此,user_id 将自始至终递增而不是清除,并且用户 id 可预测为 1、2、3 或为测试创建的许多。我可以只调用 id 而不是对预期结果进行硬编码,但稍后我真的需要它来清除更复杂示例中的内容。这是最容易展示的。任何帮助将不胜感激。

从 SPEC_HELPER.RB:

RSpec.configure do |config|

  config.mock_with :rspec
  config.include FactoryGirl::Syntax::Methods

  config.include(Capybara, :type => :integration)
  config.include Devise::TestHelpers, :type => :controller
  config.use_transactional_fixtures = false

  config.before(:each) do
    I18n.default_locale = :en
    I18n.locale = :en
    DatabaseCleaner.start
    ResqueSpec.reset!
    ActionMailer::Base.deliveries.clear
  end 

  config.after(:each) do
    DatabaseCleaner.clean
  end

  config.after(:all) do
    TestCleaner.clean
  end

  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
    DatabaseCleaner.strategy = :transaction
    Role.reset_cache!
  end

  config.after(:suite) do
    DatabaseCleaner.clean_with(:truncation)
  end

从我的测试:

      it "should return one provider" do
        get :index

        response.body.gsub(/\s+/, "").should == {
            :experts => [{
                             :availability => false,
                             :name => "#{@provider.user.first_name}#{@provider.user.last_name}",
                             :expert_id => 1,
                             :photo => @provider.details.photo.url
                         }] }.to_json
      end

      it "should show return two providers"  do
        @provider2 = create(:provider)
        get :index

        response.body.gsub(/\s+/, "").should == {
            :experts => [{
                             :availability => false,
                             :name => "#{@provider.user.first_name}#{@provider.user.last_name}",
                             :expert_id => 1,
                             :photo => @provider.details.photo.url
                         },
                         {
                             :availability => false,
                             :name => "#{@provider.user.first_name}#{@provider.user.last_name}",
                             :expert_id => 2,
                             :photo => @provider.details.photo.url
                         }
            ] }.to_json
      end
4

3 回答 3

3

数据库清理器将您的每个规范包装在一个事务中,并在规范结束时回滚该事务以删除任何数据库更改。回滚事务不会重置用于自动分配主键的自动增量或序列值。

我强烈建议不要对 id 进行硬编码。您提到您的示例将变得更加复杂,在这种情况下,在您的代码中散布随机整数将比更简单的示例更难维护。假设您使用的是 mysql,那么使用截断策略将重置自动增量值,但它也会慢很多。

于 2012-08-19T15:21:38.480 回答
1

我在开始测试时遇到了很多。我最终发现这不是由于数据库清理器问题(我也怀疑),而是由于执行测试的代码结构。

我可以尝试和描述的最好方法是说,基本上,如果你在before(:each)设置块和实际之外做事情itshould它最终会在实际测试“之外”并导致这些问题。

具体来说,我怀疑这里可能存在问题:

  it "should show return two providers"  do
    @provider2 = create(:provider)
    get :index

    response.body.gsub(/\s+/, "").should == {

我希望将其更改为更像:

  it "should show return two providers"  do
    before(:each) do { 
      @provider2 = create(:provider)
      get :index
    }

    response.body.gsub(/\s+/, "").should == {
于 2012-08-19T12:17:32.733 回答
1

是数据库没有正确清理的请求/集成规范吗?如果是这样,可能是因为您正在使用事务策略而不是截断策略进行清理。

尝试添加这个,这会将策略更改为仅针对集成规范进行截断:

config.before type: :integration do
  DatabaseCleaner.strategy = :truncation
end

您不能将事务策略用于集成规范,因为 Capybara 在具有不同数据库连接的单独线程中运行。

这篇文章在为 rspec/capybara 设置数据库方面帮助了我很多:Sane Rspec config for clean, and稍快,specs

于 2012-08-19T12:03:41.627 回答