繁体   English   中英

测试:是否有存根模型方法?

[英]Testing: Stub model methods or not?

我进行两种测试:单元测试和集成测试(对于后者,则为Cucumber / Capybara)。

对于单元测试,我想知道在测试其他类时是否存根/模拟模型方法是否是最佳实践?

# model
class Price < ActiveRecord::Base
  belongs_to :price_type, inverse_of: :prices
  belongs_to :book, inverse_of: :prices

  scope :for_book, ->(book) { where("book_id = ?", book) }
  scope :for_price_type, ->(price_type) { where("price_type_id = ?", price_type) }

  def self.latest_book_url(book, competitor)
    latest_price = for_book(book).for_competitor(competitor).last
    latest_price ? latest_price.book_url : nil
  end
end

如果我测试了调用这些作用域的类或类方法latest_book_url ,则应该模拟/存根模型的作用域和方法,还是使用FactoryGirl保存记录,然后在测试中调用模型上的方法?

# class to be tested
class PriceLister
  def initialize(book)
    @book = book
    @competitors = book.competitors
    @price_types = PriceType.all
  end

  def list_book_urls_by_competitor
    price_list = {}
    @competitors.each do |competitor|
      price_list[competitor] = {}      
      price_list[competitor][:book_url] = Price.latest_book_url(@book, competitor)
      @price_types.each do |price_type|
        price_list[competitor][price_type] = Price.for_book(@book).for_competitor(competitor).for_price_type(price_type).last
      end                
    end
    price_list
  end
end

按照定义,单元测试是单个代码单元的测试。 如果您不是在模拟/测试,那么您是在测试单个单元还是在进行小型集成测试? 最佳做法是模拟/存根进行单元测试

假设您仍然在谈论第二个问题的单元测试,那么是的,现在您应该模拟/存根已经测试过的代码。

原因很简单。 如果更改代码并破坏测试,则希望尽可能缩小导致问题的代码的范围。 如果您因为许多测试都调用相同的代码而破坏了许多测试,那么突然您将有许多测试要签出。 如果您在所有其他测试中都嘲笑了该调用,那么只有真正测试该单元的测试才会失败,而依赖于该单元的测试才能正常运行。

认为它是一个假设。 如果您假设您的方法有效,因为该方法的单元测试正在运行,并且其他工作都基于该假设,那么一切都很好,直到证明该假设是错误的为止。 那时一切都崩溃了。 另一方面,如果您认为该方法将是错误的,而是用已知结果(例如,模拟方法给出的固定结果)替换该方法,则您的其他代码将与该问题隔离。

在单元测试中,可以在测试PriceLister时从Price中提取方法。 对于Price方法,应该有单独的单元测试。

而且您的集成测试应该测试整个终端功能,而无需进行任何测试

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM