为什么这个 Rails Minitest assert_equal 因这些预期值和实际值而失败?
Why is this Rails Minitest assert_equal failing with these Expected and Actual values?
我有;
- 购物车has_many Line_items.
- A Line_item 属于购物车。
- 一个产品has_many Line_items.
- 一个Line_item属于一个产品。
在 Post 到 line_items_path 之后,product_id 被传递给 line_items_controller#create(如下所示),其中 cart#add_product 被调用(如下),它确定是否已经存在具有相同 product_id 的 line_item。如果是,则现有 line_item 的 line_item.quantity 增加 1,如果不是,则 line_item.build 然后调用 #save 以创建一个全新的行项目。
line_items_controller.rb;
def create
product = Product.find(params[:product_id])
@line_item = @cart.add_product(product.id, product.price)
respond_to do |format|
if @line_item.save
format.html { redirect_to @line_item.cart } #, notice: 'Line item was successfully created.'
format.json { render :show, status: :created, location: @line_item }
else
format.html { render :new }
format.json { render json: @line_item.errors, status: :unprocessable_entity }
end
end
end
这里是来自cart.rb;
的#add_product
def add_product(product_id, product_price)
current_item = line_items.find_by(product_id: product_id)
if current_item
current_item.quantity += 1
else
current_item = line_items.build(product_id: product_id, price: product_price)
end
current_item
end
我正在尝试测试此功能(通过 minitest),但无法理解我看到的行为。我的测试来了;
test/controllers/carts_
test "should update quantity of existing line item when adding another of the same product" do
cart = Cart.create
cart.add_product(products(:product_one).id, products(:product_one).price)
cart.add_product(products(:product_one).id, products(:product_one).price)
assert_equal cart.line_items.size, 1
# assert_equal cart.line_items[0].quantity, 2
end
测试失败,反馈;
Failure:
CartsControllerTest#test_should_update_quantity_of_existing_line_item_when_adding_another_of_the_same_product [AgileWebDev/depot/test/controllers/carts_controller_test.rb:73]:
Expected: 2
Actual: 1
我不明白,因为
a) 我已经在开发服务器上测试了行为并通过 psql
查看了表格,它的行为符合预期。
b) 我的测试断言; assert_equal cart.line_items.size, 1
预期为 1,那么为什么 Minitest 错误消息状态为 Expected: 2
。
我很困惑,经过几个小时的摸索和阅读,我无法理解我在这里做错了什么,有人可以帮忙吗?
注意 - 这是来自敏捷 Web 开发第 10 章末尾定义的额外 'playtime' 任务 Rails 5'。
a) 在您的测试用例中,购物车中没有 line_items
因为它是刚刚创建的,所以下面的行将始终 return nil
:
current_item = line_items.find_by(product_id: product_id)
因此,下面的行被调用了两次,这导致 line_items.size
为 2:
current_item = line_items.build(product_id: product_id, price: product_price)
您可以使用缓存变量来避免它:
def add_product(product_id, product_price)
@current_item ||= line_items.find_by(product_id: product_id)
if @current_item
@current_item.quantity += 1
else
@current_item = line_items.build(product_id: product_id, price: product_price)
end
@current_item
end
b) 根据Rails's Minitest的介绍,断言的格式应该是
assert_equal( expected, actual, [msg] )
这就是你的断言信息出错的原因。正确的是
assert_equal 1, cart.line_items.size, "should has only 1 item"
针对 b 部分的回应:如果您查看 assert_equal 的 APIdocks,预期值首先出现,然后是实际值。所以你写的 1
被 Minitest 当作实际值,而期望值是 cart.line_items.size
我不确定为什么 cart.line_items.size
等于 B。假设您对开发服务器和 psql 的观察是正确的,这可能与您的测试条件设置方式有关。如果在添加行项目的代码之前添加 assert_equal 0, cart.line_items.size
会发生什么情况?
test "should update quantity of existing line item when adding another of the same product" do
cart = Cart.create
assert_equal 0, cart.line_items.size
cart.add_product(products(:product_one).id, products(:product_one).price)
cart.add_product(products(:product_one).id, products(:product_one).price)
assert_equal cart.line_items.size, 1
# assert_equal cart.line_items[0].quantity, 2
end
我有;
- 购物车has_many Line_items.
- A Line_item 属于购物车。
- 一个产品has_many Line_items.
- 一个Line_item属于一个产品。
在 Post 到 line_items_path 之后,product_id 被传递给 line_items_controller#create(如下所示),其中 cart#add_product 被调用(如下),它确定是否已经存在具有相同 product_id 的 line_item。如果是,则现有 line_item 的 line_item.quantity 增加 1,如果不是,则 line_item.build 然后调用 #save 以创建一个全新的行项目。
line_items_controller.rb;
def create
product = Product.find(params[:product_id])
@line_item = @cart.add_product(product.id, product.price)
respond_to do |format|
if @line_item.save
format.html { redirect_to @line_item.cart } #, notice: 'Line item was successfully created.'
format.json { render :show, status: :created, location: @line_item }
else
format.html { render :new }
format.json { render json: @line_item.errors, status: :unprocessable_entity }
end
end
end
这里是来自cart.rb;
的#add_productdef add_product(product_id, product_price)
current_item = line_items.find_by(product_id: product_id)
if current_item
current_item.quantity += 1
else
current_item = line_items.build(product_id: product_id, price: product_price)
end
current_item
end
我正在尝试测试此功能(通过 minitest),但无法理解我看到的行为。我的测试来了;
test/controllers/carts_
test "should update quantity of existing line item when adding another of the same product" do
cart = Cart.create
cart.add_product(products(:product_one).id, products(:product_one).price)
cart.add_product(products(:product_one).id, products(:product_one).price)
assert_equal cart.line_items.size, 1
# assert_equal cart.line_items[0].quantity, 2
end
测试失败,反馈;
Failure:
CartsControllerTest#test_should_update_quantity_of_existing_line_item_when_adding_another_of_the_same_product [AgileWebDev/depot/test/controllers/carts_controller_test.rb:73]:
Expected: 2
Actual: 1
我不明白,因为
a) 我已经在开发服务器上测试了行为并通过 psql
查看了表格,它的行为符合预期。
b) 我的测试断言; assert_equal cart.line_items.size, 1
预期为 1,那么为什么 Minitest 错误消息状态为 Expected: 2
。
我很困惑,经过几个小时的摸索和阅读,我无法理解我在这里做错了什么,有人可以帮忙吗?
注意 - 这是来自敏捷 Web 开发第 10 章末尾定义的额外 'playtime' 任务 Rails 5'。
a) 在您的测试用例中,购物车中没有 line_items
因为它是刚刚创建的,所以下面的行将始终 return nil
:
current_item = line_items.find_by(product_id: product_id)
因此,下面的行被调用了两次,这导致 line_items.size
为 2:
current_item = line_items.build(product_id: product_id, price: product_price)
您可以使用缓存变量来避免它:
def add_product(product_id, product_price)
@current_item ||= line_items.find_by(product_id: product_id)
if @current_item
@current_item.quantity += 1
else
@current_item = line_items.build(product_id: product_id, price: product_price)
end
@current_item
end
b) 根据Rails's Minitest的介绍,断言的格式应该是
assert_equal( expected, actual, [msg] )
这就是你的断言信息出错的原因。正确的是
assert_equal 1, cart.line_items.size, "should has only 1 item"
针对 b 部分的回应:如果您查看 assert_equal 的 APIdocks,预期值首先出现,然后是实际值。所以你写的 1
被 Minitest 当作实际值,而期望值是 cart.line_items.size
我不确定为什么 cart.line_items.size
等于 B。假设您对开发服务器和 psql 的观察是正确的,这可能与您的测试条件设置方式有关。如果在添加行项目的代码之前添加 assert_equal 0, cart.line_items.size
会发生什么情况?
test "should update quantity of existing line item when adding another of the same product" do
cart = Cart.create
assert_equal 0, cart.line_items.size
cart.add_product(products(:product_one).id, products(:product_one).price)
cart.add_product(products(:product_one).id, products(:product_one).price)
assert_equal cart.line_items.size, 1
# assert_equal cart.line_items[0].quantity, 2
end