ruby-on-rails 如何让Rspec在rails 6中为读取器和写入器DB使用相同的DB连接?

g2ieeal7  于 2023-02-01  发布在  Ruby
关注(0)|答案(1)|浏览(106)

对于上下文,这个问题之所以出现,是因为我们正在从Rails 5迁移到Rails 6,并且通过新的复制特性引入了读取器/写入器数据库连接。
我们的具体问题是请求规范,着眼于使用事务性fixture。当我们单独运行请求规范文件时,它们通过。当作为多文件传递的一部分运行时(例如在circle CI上使用完整的bundle exec parallel_rspec传递),它们失败。如果我们关闭事务性fixture,测试运行时间太长,但通过了。
使用byebug,我们已经插入并确定问题在于我们的测试数据已经被写入到writer DB连接/可以被writer DB连接访问,但是路由尝试使用reader DB连接来读取它,即ActiveRecord::Base.connected_to(role: :reading) { puts Foo.count }是0,而连接到writing角色的相同代码是非零的。
由此产生的问题似乎相当明显:因为我们使用的是事务性测试/fixture,所以代码永远不会提交到数据库。它只在连接上可用。请求规范从“正确”的数据库中阅读调用(GET请求应该使用reader数据库),但在测试用例中会产生错误。
这似乎是一个相当明显的用例,Rails或rspec * 应该 * 有一个工具来处理,我们只是似乎无法找到相关的文档。

s6fujrry

s6fujrry1#

您需要告诉测试环境,它应该为这两个连接使用一个连接。有多种方法可以做到这一点:
1.您可以将test环境配置为根本不使用副本。有关使用副本和不使用副本的示例,请参阅设置应用程序,然后在database.yml中重现非副本版本(仅用于测试环境)。
1.你可以在你的规范中使用connected_to,这样那些测试就会被强制使用你希望它们使用的特定连接。一种方法是使用around钩子:

describe "around filter" do
  around(:each) do |example|
    puts "around each before"
    ActiveRecord::Base.connected_to(role: :writing) { example.run }
    puts "around each after"
  end

  it "gets run in order" do
    puts "in the example"
  end
end

1.您可以在rails_helper中修补ActiveRecord配置,这样它就不会使用副本(但我真的建议使用#1而不是此选项)

相关问题