Raymond Peterfellow
Raymond Peterfellow

Reputation: 634

Minitest - How do you test a method isn't invoked?

I'm trying to check if a method isn't invoked within an after_update callback.

I'm currently doing:

class Foo
  def self.call; end
end

def Model < ActiveRecord::Base
  after_update :do_something

  def do_something
    return unless title_changed?

    Foo.call
  end
end

In the test it works like that:

test 'Foo.new.bar is invoked' do
  mock = Minitest::mock.new
  mock.expect :call, nil
  Foo.stub(:call) { update_record_to_fire_callback }
  mock.verify 
end

And it beautifully pass, but now I'm trying to do the opposite but without luck as I don't know how to do it. If I do assert_not mock.verify Minitest complains anyway for the method to be executed.

Or maybe there are other way to check a method isn't invoked? The method will do an expensive request, so, I want to avoid that.

I'm using Rails 5 and sadly Minitest. I'm open to add any gem that can work with these versions.

Upvotes: 2

Views: 3138

Answers (2)

Mike H
Mike H

Reputation: 86

Since you're open to adding a gem, mocha works well for this. Add the gem, then use mocha's Expectation#never. Your test can then look like:

test 'Foo.new.bar is not invoked' do
  model = Model.new
  Foo.expects(:call).never
  model.update!(not_the_title: 'value') 
end

Upvotes: 5

blowmage
blowmage

Reputation: 8984

The easiest way to accomplish this is to stub the method that you want to ensure isn't called and have it raise an error.

class ModelTest < ActiveSupport::TestCase
  test "does not call Foo.call when title is not changed" do
    model = Model.new
    refute model.title_changed?

    Foo.stub(:call, -> { raise "Foo was called!" }) do
      model.title = "something new"
    end

    assert model.title_changed?
  end
end

There is no assertion to check that an error was not explicitly raised. Rails does have assert_nothing_raised, but Minitest does not. You can add it if you like.

class ModelTest < ActiveSupport::TestCase
  test "does not call Foo.call when title is not changed" do
    model = Model.new
    refute model.title_changed?

    Foo.stub(:call, -> { raise "Foo was called!" }) do
      assert_nothing_raised do
        model.title = "something new"
      end
    end

    assert model.title_changed?
  end
end

Upvotes: 1

Related Questions