【问题标题】:Right way of testing service used by controller控制器使用的测试服务的正确方法
【发布时间】:2016-11-04 19:57:30
【问题描述】:

给定下面的代码:

class FooController < ApplicationController
  def create
    if auth_is_alright && params_are_cool #pseudocode
      @bar_results = BarService.new(param).run
    end
  end
end

class BarService
  def initialize(params)
    @transaction_token = params[:transaction_token]
    @id = params[:id]
    @quantity = params[:quantity]
    @value = params[:value]
    if Transaction.where(token: @transaction_token).any?
      _undo_previous_run    
    end
  end

  def run
    Transaction.new(token: @transaction_token, product_id: @id, quantity: @quantity, value: @value).save!
    product = Product.find(id: @id)
    product.update!(stock_quantity: product.stock_quantity - @quantity)
  end

private

  def _undo_previous_run
    transaction = Transaction.find_by_token(@transaction_token)
    product = Product.find(id: transaction.product_id)
    product.update!(stock_quantity: product.stock_quantity + transaction.quantity)
    transaction.destroy
  end

end

现在我的问题是,应该在哪里测试 _undo_previous_run 行为的正确位置?:

  • BarServiceSpec?
  • FooControllerSpec? (调用创建操作等)
  • 其他?

【问题讨论】:

    标签: ruby ruby-on-rails-4 rspec tdd


    【解决方案1】:

    测试通常用作类 API 的“文档”。 _undo_previous_run 是私有方法,不能直接访问。我更喜欢测试/描述公共方法的行为。

    在这种情况下,您需要测试BarService.new 方法。

    【讨论】:

    • 你不考虑更“外部”地测试它,就像在 FooControllerSpec 中一样,用相同的参数调用 create 操作两次并检查它的结果吗?如果不是,为什么?
    • 如果您的目标是确保每次调用后的返回值相同,那么这是一个好方法。您需要编写尽可能少的测试,但足以涵盖所有有价值的功能。对于BarService.new,我将编写下一个测试:设置每个实例变量;将stock_quantity 更新为product;使用令牌(如果存在)删除 transaction
    猜你喜欢
    • 1970-01-01
    • 2018-12-31
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    • 2014-07-20
    相关资源
    最近更新 更多