如何测试一个方法在对象中被另一个调用?

时间:2019-12-23 14:47:42

标签: ruby-on-rails ruby minitest

我有以下课程:

class Foo
  def initialize(foobar:)
    @foobar = foobar
  end

  def call
    return if foobar.blank?
    do_something_here
  end
end

正在从模型的after_commit回调中调用哪个

included { after_commit :invoke_method_in_poro, on: %I[create update] }

private

def invoke_method_in_poro
  Foo.new(foobar: to_json).call
end

现在,当我尝试测试是否正在调用call时,我需要先对新方法进行存根处理,因为出现此错误:

NameError: undefined method `call' for class `Foo'
Did you mean?  caller

使用以下代码:

foo = Foo
new_mock = Minitest::Mock.new
new_mock.expect :call, nil
foo.stub(:call, new_mock) do
  create(:model)
end
mock.verify

我的问题是,我最终如何才能测试call被调用了?

1 个答案:

答案 0 :(得分:1)

您在这里遇到了Minitest的特殊性:当在方法上定义call时,看来minitest堆栈中的某些对象在定义对象时会尝试调用它。

给出此测试设置:

require 'minitest/autorun'

class Foo
  def call
  end
end

class Bar
  def test
    Foo.new.call
  end
end

describe "Bar" do
  it "invokes foo.call" do
    mock = Minitest::Mock.new(Foo)
    mock.expect(:call, nil)

    Foo.stub :new, mock do |args|
      Bar.new.test
      mock.verify
    end
  end
end

它如所述失败。但是,如果将call重命名为my_call,它将通过:

require 'minitest/autorun'

class Foo
  def my_call
  end
end

class Bar
  def test
    Foo.new.my_call
  end
end

describe "Bar" do
  it "invokes foo.my_call" do
    mock = Minitest::Mock.new(Foo)
    mock.expect(:my_call, nil)

    Foo.stub :new, mock do |args|
      Bar.new.test
      mock.verify
    end
  end
end

同一测试通过RSpec:

class Foo
  def call
  end
end

class Bar
  def test
    Foo.new.call
  end
end

describe "Bar" do
  it "invokes foo.call" do
    mock = double
    expect(mock).to receive(:call)
    expect(Foo).to receive(:new).and_return(mock)
    Bar.new.test
  end
end