0

我正在关注《使用 Rails 进行敏捷 Web 开发》(第 4 版)这本书,但我遇到了一个失败的测试用例的麻烦。

我写了一个测试,检查当您将重复的商品添加到购物车时,商品的数量没有变化,但数量会发生变化

  test 'adding duplicate products to cart' do
    cart = Cart.new

    ruby_book = products(:ruby)
    cart.add_product ruby_book.id

    assert cart.line_items.length == 1
    assert cart.total_price == ruby_book.price

    p '-------start--------'
    p 'outside add_product'
    p "line_items: #{cart.line_items}"
    cart.add_product ruby_book.id

    assert cart.line_items.length == 1  # TEST FAILS HERE with length == 2
    assert cart.total_price == ruby_book.price * 2 
  end 

它基本上测试了add_product方法,即:

class Cart < ActiveRecord::Base
  has_many :line_items, dependent: :destroy

  def add_product(product_id)
    p 'inside add_product'
    p "line_items: #{line_items}"
    p "product_id: #{product_id}"
    current_item = line_items.find_by_product_id(product_id)
    p "current_item: #{current_item}"
    p '---------end---------'
    if current_item
      current_item.quantity += 1
      current_item.price += current_item.product.price
    else
      current_item = line_items.build(product_id: product_id)
      current_item.price = current_item.product.price
    end 
    current_item
  end 

  def total_price
    line_items.to_a.sum { |item| item.price }
  end 
end

为了调试测试,我添加了一些打印调用(如您所见)。输出是:

"-------start--------"
"outside add_product"
"line_items: [#<LineItem id: nil, product_id: 207281424, cart_id: nil, created_at: nil, updated_at: nil, quantity: 1, price: #<BigDecimal:7fa491744fe0,'0.4999E2',18(45)>>]"
"inside add_product"
"line_items: [#<LineItem id: nil, product_id: 207281424, cart_id: nil, created_at: nil, updated_at: nil, quantity: 1, price: #<BigDecimal:7fa491744fe0,'0.4999E2',18(45)>>]"
"product_id: 207281424"
"current_item: "
"---------end---------"

我可以看到line_items有一个项目,product_id: 207281424但由于某种原因,调用line_items.find_by_product_id(product_id)不会返回项目,而是返回nil. 为什么?

4

3 回答 3

0

迪默是正确的。您没有将商品保存到购物车中。

current_item = line_items.find_by_product_id(product_id)如果您不保存,将返回nil并导致您构建另一个。line_item导致您的测试返回 2 而不是 1。

然后是你的total_price方法的问题。

line_items.to_a.sum { |item| item.price }

在您的场景中(保存到数据库)只会总结1 个行项目,因为您要添加两次相同的产品。如果不保存(到 db),数学将是正确的,因为每个行项目将充当 1 个数量。

由于数量是按行项目定义的,因此您需要确保将数量应用于计算。

line_items.to_a.sum { |item| item.price * item.quantity }
于 2012-12-24T17:42:02.517 回答
0

问题出在你的add_cart方法上。在 else 块中,您只是在构建一个line_item对象,但您没有将其保存在任何地方。将您的其他阻止更改为,

else
  current_item = line_items.build(product_id: product_id)
  current_item.price = current_item.product.price
  current_item.save
end 
于 2012-12-24T13:05:37.913 回答
0

add_product方法不将行项目保存在数据库中,尝试调用save返回的项目

...
ruby_book = products(:ruby)
item = cart.add_product ruby_book.id
item.save

assert cart.line_items.length == 1
assert cart.total_price == ruby_book.price


item = cart.add_product ruby_book.id
item.save

assert cart.line_items.length == 1
...
于 2012-12-24T13:07:32.677 回答