DEV Community

Vasily Polovnyov
Vasily Polovnyov

Posted on

RSpec & Rails: how to test callbacks

Sometimes it's not clear which way to approach a complex callback and how to test it. For example, in the situation with a post:

class Post < ApplicationRecord
  before_save :set_permalink
  after_save :rebuild_preview

  private

  def set_permalink
    self.permalink ||= build_permalink
  end

  def build_permalink
    date.strftime("%Y/%-m/") + title.parameterize("-")
  end

  def rebuild_preview
    Preview.new(self).rebuild
  end
end
Enter fullscreen mode Exit fullscreen mode

The first thing that comes to mind is to test callbacks directly with send. Please don't do so. It is private methods which are subject to change.

Instead it'd be better to test the public interface which uses those callbacks (before or after save → #save):

describe "#save"
  context "when permalink is NOT set" do
    it "generates it from year, month and title" do
      post = Post.create(
        date: new Date(2016, 07, 07),
        title: "Hello, its me")

      expect(post.permalink).to eq "2016/7/hello-its-me"
    end
  end

  context "when permalink is set" do
    it "preserves it" do
      post = Post.new(
        title: "Some title",
        permalink: "some-special-post")

      expect { post.save }.not_to change { post.permalink }
    end
  end

  if "rebuilds preview" do
    preview = instance_double(Preview, rebuild: true)
    post = Post.new(title: "Some title")
    allow(Preview).to receive(:new).and_return(preview)

    post.save

    expect(preview).to have_received(:rebuild)
  end
end
Enter fullscreen mode Exit fullscreen mode

Top comments (0)