我在模型中有一个方法:

class Article < ActiveRecord::Base
  def do_something
  end
end

我还对这种方法进行了单元测试:

# spec/models/article_spec.rb
describe "#do_something" do
  @article = FactoryGirl.create(:article)
  it "should work as expected" do
    @article.do_something
    expect(@article).to have_something
  end
  # ...several other examples for different cases
end

一切都很好,直到我发现最好将此方法移到after_save回调中:

class Article < ActiveRecord::Base
  after_save :do_something

  def do_something
  end
end

现在我所有关于这个方法的测试都失败了.我必须通过以下方式解决它:

  • 没有更具体的do_something调用,因为createsave也将触发此方法,否则我将遇到重复的db操作.
  • create换成build
  • 测试响应
  • 使用常规model.save而不是单个方法调用model.do_something

    describe "#do_something" do
      @article = FactoryGirl.build(:article)
      it "should work as expected" do
        expect{@article.save}.not_to raise_error
        expect(@article).to have_something
        expect(@article).to respond_to(:do_something)
      end
    end
    

测试通过了,但我担心的是,这不再是具体的方法.效果是mixed with other callbacks if more added.

我的问题是,有没有什么漂亮的方法来测试model的实例方法independently,使其成为回调?

推荐答案

回调和回调行为是独立的测试.如果要判断after_save回调,需要将其视为两件事:

  1. 是否为正确的事件触发回调?
  2. 被调用的函数做得对吗?

假设您有Article个类,其中包含许多回调,下面是测试方法:

class Article < ActiveRecord::Base
  after_save    :do_something
  after_destroy :do_something_else
  ...
end

it "triggers do_something on save" do
  expect(@article).to receive(:do_something)
  @article.save
end

it "triggers do_something_else on destroy" do
  expect(@article).to receive(:do_something_else)
  @article.destroy
end

it "#do_something should work as expected" do
  # Actual tests for do_something method
end

这将使回调与行为分离.例如,当其他相关对象被更新时,比如user.before_save { user.article.do_something },可以触发相同的回调方法article.do_something.这将容纳所有这些.

所以,像往常一样继续测试你的方法.分别担心回拨.

编辑:打字错误和潜在的误解

Ruby-on-rails相关问答推荐

使用Hotwire/Turbo的Rails在链接悬停时获取请求

有没有一种方法可以点击一个按钮来冒泡到父元素?

Selenium chromedriver:无法从不可键入的键构造KeyEvent

如何从设计中删除/禁用注册

Devise + Omniauth - 如何传递额外的参数?

Rails Migration将字符串转换为整数?

使用brew 软件安装了 elasticsearch,但找不到配置文件

I18n 用于特定于模型的 Rails 提交按钮

骨干model.destroy()即使工作正常也会调用错误回调函数?

有没有办法在模型而不是视图中使用复数()?

在 Rails/ActiveRecord 列名中使用问号字符

Rails 3.1 在开发模式下非常慢,因为assets资源 ,怎么办?

如何让空白复选框作为假传递给参数

Rails 引擎中的迁移?

Rails:使用 gem 卸载特定版本的库

对象不支持此属性或方法 Rails Windows 64bit

Ruby on Rails - link_to 按钮 / css

为什么 RSpec 在 Rails 下这么慢?

列出关联模型的名称

如何删除特殊字符?