Capybara JS测试即使在禁用事务后也无法访问DB设备

Capybara JS tests unable to access DB fixtures even after disabling transactions

本文关键字:访问 设备 DB 事务 测试 JS Capybara      更新时间:2023-09-26

我不久前刚刚了解到,Capybara为Javascript测试启动了一个单独的服务器和数据库连接,这意味着在before块中设置的数据库数据在测试期间不可用。

正如这篇流行文章中所描述的,该应用程序配置如下,以禁用事务固定装置

RSpec.configure do |config|
  config.use_transactional_fixtures = false
  Capybara.configure do |config|
    config.javascript_driver = :webkit
  end
  config.before(:suite) do
    DatabaseCleaner.clean_with(:deletion)
  end
  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end
  config.before(:each, :js => true) do
    DatabaseCleaner.strategy = :deletion
  end
  config.before(:each) do
    DatabaseCleaner.start
  end
  config.after(:each) do
    DatabaseCleaner.clean
  end
end

理想情况下,这应该在所有启用JS的测试中使用:deletion方法,并避免以事务方式插入数据。

我用一个简单的测试来尝试它,用户用自己的名字填写一个非常简单的注册表并提交

describe "Registration Process" do
  let(:user) { create(:user) }
  before(:each) do
    # Logs a fake user in and sets the session store so `current_user` in the Controller calls this user
    sign_in(user)
    visit registration_path
  end
  describe "Registration Form", js: true do
    before(:each) do
      fill_in :name, with: "Julio Jones"
      click_button("Submit")
    end

    it "sets the user's name" do
      expect(user.reload.name).to eq("Julio Jones")
    end
  end
end

这是提交表单时调用的控制器操作。非常简单-

class UsersController < ApplicationController
  def update
    current_user.update(name: params[:name])
  end
end

我的问题是,在控制器内部,它根本看不到数据库中的User记录

  1. 如果我暂停规范before块中的执行,我可以看到到目前为止创建的1个User记录(User.count=1)
  2. 如果我在正在测试的代码内暂停执行(即控制器操作),则我可以看到User对象(current_user.present?true),但我<strong]不能>查看DB中的记录(User.count=0)

这告诉我User模型对象被正确地存储和检索,但它使用不同的DB连接,因为DB表中没有存储物理备份记录。

更奇怪的是,我可以确认它不是以事务方式运行的。

ActiveRecord::Base.connection.open_transactions # => 0

还有什么可以阻止它查看数据库记录的想法吗?它与使用:webkit作为Javascript驱动程序有什么关系吗?我知道我在网上看到的大多数使用:selenium 的例子

谢谢!

如果水豚和服务器看到的匹配,我想知道如何调试。尝试输出到视图数据库记录。这只是一个猜测,但我认为这样你可能会发现水豚和服务器数据库状态不匹配。

实际上我也有同样的问题,但我用的是minitest。您确定DatabaseCleaner命令的执行顺序正确吗?尝试在中显式.start

config.before(:each, :js => true) do
    DatabaseCleaner.strategy = :deletion
    DatabaseCleaner.start
end

在我的案例中,它已经从事务策略开始,所以当您在不使用.start的情况下动态更改策略时,DatabaseCleaner会使用旧策略。