【问题标题】:Using RSpec to test an action class that instantiates a service class使用 RSpec 测试实例化服务类的操作类
【发布时间】:2017-12-22 19:26:43
【问题描述】:

我正在使用基于操作/服务的架构,其中服务类托管 HTTP 调用,操作类清理/打包数据并调用服务类以与外部 API 对话。设置工作正常,但我想知道如何为动作类设置模拟。这是一个示例操作/服务对:

# Service
class UserService
  def update_user user_id, data
    # make request
  end
end

# Action
class UserUpdate
  def initialize user_id, user_data
    @id = user_id
    @sanitized_data = user_data
  end

  def call
    service = UserService.new
    service.call(@id, @sanitized_data)
  end
end

我可以毫无问题地模拟操作,但是当我尝试为服务使用类或实例替身时,我得到了错误。到目前为止,这是我的测试:

it "should create an instance of Agent Service" do
  agent_action_mock = class_double("AgentUpdate")
  agent_service_mock = class_double("AgentService")

  allow(agent_update_mock).to receive_message_chain(:new, :call)
  allow_any_instance_of(AgentService).to receive_message_chain(:initialize, :update_user)

  agenta_action_mock.new(99, { status: "Verified" }).call
  expect_any_instance_of(AgentService).to receive(:initialize)
end

这让我很开心Failure/Error: DEFAULT_FAILURE_NOTIFIER = lambda { |failure, _opts| raise failure } Exactly one instance should have received the following message(s) but didn't: initialize

我想知道如何测试该操作是否正在创建服务类的实例并调用它的方法?

【问题讨论】:

  • 但是你确定它真的被调用了吗?

标签: ruby-on-rails ruby unit-testing rspec


【解决方案1】:

我发现您的测试存在一些问题。 首先,您在模拟上调用方法。除非您将方法设置为call_original,否则双精度的所有方法都会被存根并且什么都不做。所以没有办法调用double的方法来触发实际的行为。

其次,由于您在测试结束时使用了期望,因此您应该使用期望的间谍形式 - have_received。否则,它会在设置了期望之后寻找 :initialize 的调用,这永远不会发生。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-20
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    相关资源
    最近更新 更多