如何在MiniTest中使用假的测试硬编码类

时间:2016-01-26 11:39:46

标签: ruby-on-rails testing mocking minitest stubs

我有一个调用PlantTree服务对象的PlantTree作业。我想测试这项工作,以确定它使用PlantTree参数实例化tree服务并调用call方法。

我对服务的作用或结果不感兴趣。它有自己的测试,我不想重复这些测试。

# app/jobs/plant_tree_job.rb
class PlantTreeJob < ActiveJob::Base
  def perform(tree)
    PlantTree.new(tree).call
  end
end

# app/services/plant_tree.rb
class PlantTree
  def initialize(tree)
    @tree = tree
  end

  def call
    # Do stuff that plants the tree
  end
end

如您所见,PlantTree类在作业的perform方法中进行了硬编码。所以我不能伪造它并将其作为依赖项传递。有没有办法可以在执行方法的生命周期内伪造它?有点像...

class PlantTreeJobTest < ActiveJob::TestCase
  setup do
    @tree = create(:tree)
  end

  test "instantiates PlantTree service with `@tree` and calls `call`" do
    # Expectation 1: PlantTree will receive `new` with `@tree`
    # Expectation 2: PlatTree will receive `call`
    PlantTreeJob.perform_now(@tree)
    # Verify that expections 1 and 2 happened.
  end
end

我正在使用Rails的默认堆栈,它使用MiniTest。我知道这可以用Rspec完成,但我只对MiniTest感兴趣。如果不能仅使用MiniTest或默认的Rails堆栈,我可以使用外部库。

3 个答案:

答案 0 :(得分:1)

您应该可以执行类似

的操作
mock= MiniTest::Mock.new
mock.expect(:call, some_return_value)
PlantTree.stub(:new, -> (t) { assert_equal(tree,t); mock) do
  PlantTreeJob.perform_now(@tree)
end
mock.verify

这将在PlantTree上存根新方法,将参数检查到树,然后返回模拟而不是PlantTree实例。该模拟进一步验证调用是否被调用。

答案 1 :(得分:0)

不确定如何在Minitest中编写此内容,但您可以使用mock(此处为RSpec语法):

expect(PlantTree).to receive(:new).with(tree)
expect_any_instance_of(PlantTree).to receive(:call)
# NOTE: either of the above mocks (which are expectations)
# will fail if more than 1 instance receives the method you've mocked -
# that is, PlantTree#new and PlantTree#call
# In RSpec, you can also write this using `receive_message_chain`:
# expect(PlantTree).to receive_message_chain(:new, :call)
job = PlantTreeJob.new(@tree)
job.perform

除非PlantTree服务对象(1)通过#new实例化,并且(2)获得#call',否则此测试将失败。

免责声明:这可能不是100%功能,但这应该是正确的想法,假设我已正确读取OP的Q。

答案 2 :(得分:0)

plant_tree_mock= MiniTest::Mock.new
dummy = Object.new
tree = Object.new
plant_tree_mock.expect(:call, dummy, [tree])

PlantTree.stub(:new, plant_tree_mock) do
  PlantTreeJob.perform_now(tree)
end

assert plant_tree_mock.verify