为什么模型在重新加载后在数据库中包含旧数据?

Why model contains old data in DB after reload?

before(:all) 不应该只执行一次吗?在我的示例中,底部测试失败,因为数据库记录包含旧数据(名称 == "John")。为什么这样?我在上面的测试中将其更改为 "Irow".

describe "Widget" do
before(:all) do
  @widget = Widget.create(name: "John")
end

it "changes Widget's #name in DB" do
  expect do
    @widget.name = "Irow"
    @widget.save!
  end.to change { @widget.reload.name}.from("John").to("Irow")
end

it "#name must be updated in DB by previous test" do
  expect(@widget.reload.name).to eq("Irow") # failing test
end

结束

此答案假定在您的 rails_helper.rbspec_helper.rb 中有一行 config.use_transactional_fixtures = true.

您的测试所做的是 运行 每个测试都在一个专用事务中,并在测试完成后回滚该事务。

您的第一个测试会将 @widget 名称更改为 Irow,成功通过并将更改回滚到数据库。

这会让您在测试后处于

@widget.name == "Irow"

但是

@widget.reload.name == "John"

由于将名称更改为 Irow 的事务已回滚,因此数据库中的行再次具有 John

另一件值得一提的事情是,您可能 运行 以随机顺序进行测试 (config.order = :random),因此如果您不是 运行 每个,您的测试就会闪烁在专用事务中进行测试。

尽量使您的测试尽可能独立,仅在确实有意义时才使用before(:all)(也许对于一些非常昂贵的操作)。