我正在关注这本书Agile Web Development with Rails (4th edition),而我在测试失败的情况下遇到了麻烦。
我写了一个测试,检查当你将重复的项目添加到购物车时,项目数量不会改变,但数量会发生变化
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
。为什么呢?
答案 0 :(得分: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
答案 1 :(得分: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
...
答案 2 :(得分: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 订单项,因为您要添加两次相同的产品。如果没有保存(到数据库),数学将是正确的,因为每个行项目将作为1个数量。
由于每个订单项都定义了数量,因此您需要确保将数量应用于计算。
line_items.to_a.sum { |item| item.price * item.quantity }