【问题标题】:RSpec - Can't mock ActiveRecord model classRSpec - 无法模拟 ActiveRecord 模型类
【发布时间】:2021-08-27 21:12:59
【问题描述】:

试图在 RSpec 单元测试中模拟 ActiveRecord 模型类。在这里我总结一下。

RSpec 测试

it 'calls create method' do
  response_code = post @url, params: { id: @id }
  expect(response_code).to eql(200)

  allow(MyModel).to receive(:create)

  expect(MyModel).to receive(:create)
end

控制器方法

控制器入口点。

def controller_method
  other_model_method
  #...
  render json: #...
end

调用 MyModel 的其他模型

Class OtherModel < ActiveRecord
  #...

  def other_model_method
    MyModel.create(attr: value)
  end
end

运行我得到的测试:

(MyModel(id: integer).create(*(any args))
           expected: 1 time with any arguments
           received: 0 times with any arguments

我是 Rails 和 Ruby 的新手。这对 allow(MyModel)/expect(MyModel) 我在另一篇文章中看到但不适合我。我做错了什么?

【问题讨论】:

  • 从问题中不清楚您实际上要完成什么或实际上应该测试什么行为。 “调用创建方法”不是一种行为 - 它是实现。 allow(MyModel).to receive(:create) 将用模拟替换原始方法。 expect(MyModel).to receive(:create) 也存根该方法,但它也设定了该方法应该/已经被调用的期望。 relishapp.com/rspec/rspec-mocks/v/3-10/docs/basics

标签: ruby-on-rails ruby rspec mocking


【解决方案1】:

首先,最好在触发操作之前进行allow 调用。然后,您需要使用过去时匹配器来检查您的模拟是否被调用。

养成这种习惯的好处是,您在测试中使用相同的风格,您只需要模拟一些东西,就像您关心为这些模拟设定期望时一样。

类似这样的:

it 'calls create method' do
  allow(MyModel).to receive(:create)

  response_code = post @url, params: { id: @id }

  expect(response_code).to eq(200)
  expect(MyModel).to have_received(:create).with(some: value)
end

您可以将 some: value 替换为您希望调用模拟的任何内容。

如果您在同一规范中的大量测试中执行此操作,则可以将 allow 调用转移到 before 块。像这样:

before do
  allow(MyModel).to receive(:create)
end

it 'calls create method' do
  response_code = post @url, params: { id: @id }

  expect(response_code).to eq(200)
  expect(MyModel).to have_received(:create).with(some: value)
end

【讨论】:

  • 在调用被测代码之前或之后设置期望都是有效的选项,并且选择实际上更多的是样式问题。使用 AAA 和 GWT 更好地设置测试后的期望值。
【解决方案2】:

您的模拟期望应该在代码调用它们之前发生在测试中,所以

it 'calls create method' do
   expect(MyModel).to receive(:create)

   response_code = post @url, params: { id: @id }
   expect(response_code).to eql(200)
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-20
    • 1970-01-01
    • 2020-02-26
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多