【问题标题】:How to get rid of necessarily reloading in RSpec?如何摆脱 RSpec 中的必要重新加载?
【发布时间】:2012-10-21 05:22:14
【问题描述】:

我在运行规范时遇到了一个奇怪的行为。

除非我取消注释行 baz.reload,否则此代码不起作用(baz.viewed 未更新)。

describe "#..." do
  it "..." do
    baz = user.notifications.create!(title: "baz")
    baz.update_attribute(:created_at, Time.now + 3.day)

    # it sets `viewed` to `true` in the model to which `baz` is referred.
    user.dismiss_latest_notification!

    # baz.reload
    baz.viewed.should == true
  end
end

我不使用 SporkGuard 运行规范,但无论如何都不会重新加载此模型。

为什么会发生?或者,在规范中调用 .reload 方法是否正常?

【问题讨论】:

  • 这是正常的。更新属性时应该调用reload

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


【解决方案1】:

让我让这个案例更清楚一点: 当baz = user.notifications.create!(title: "baz") 行被执行时,会发生两件事:

1- 一个新的通知行被添加到数据库中。

2- 在内存中创建一个对象,表示这一行,并且可以使用变量baz 引用。 请注意,baz 的查看值为 false(同时该行也是如此)。

现在我没有看到方法的实际实现

user.dismiss_latest_notification!

但是由于您没有将任何变量传递给它,我当然知道您有一个本着以下精神的代码:

def dismiss_latest_notification!
  latest_notification = self.notifications.last
  latest_notification.viewed = true
  latest_notification.save!
end

这里重要的一行是

   latest_notification = self.notifications.last

在内存中创建了一个对象,表示 baz 所做的同一行,但存储在另一个变量 - latest_notification 中。

现在您有两个变量代表数据库中的同一行。当您在 latest_notification 上执行保存时,DB 会使用正确的查看值更新,但变量 baz 不会以任何方式更新以反映此更改。您别无选择,只能通过对其执行reload 来强制使用最新值从数据库更新。

我认为摆脱重载的正确方法是稍微改变一下测试:

代替

baz.viewed.should == true

用途:

user.notifications.last.viewed.should be_true

在我看来,它更适合这个特定测试的目的。

【讨论】:

  • 感谢您的解释,现在对我来说很有意义:)
猜你喜欢
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-14
  • 1970-01-01
  • 1970-01-01
  • 2019-03-22
相关资源
最近更新 更多