我有;
在post to 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 "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
。
我很困惑,经过几个小时的头部划伤和阅读后,我无法理解我在这里做错了什么,有人可以帮忙吗?
注意 - 这是来自使用Rails 5'的Agile Web Development第10章末定义的额外'playtime'任务。
答案 0 :(得分:1)
a)在您的测试用例中,购物车中没有line_items
,因为它刚刚创建,因此下面的行始终会返回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"
答案 1 :(得分:0)
回应b部分:如果你看一下assert_equal的APIdocks,首先是预期值,然后是实际值。因此,您编写的def mergeList(arr, pos, res, start, mid, end):
temp = [0]*len(arr)
for i in range(start, end+1):
temp[i] = pos[i]
cur = start
leftcur = start
rightcur = mid + 1
while leftcur <= mid and rightcur <= end:
if arr[temp[leftcur]] <= arr[temp[rightcur]]:
pos[cur] = temp[leftcur]
res[pos[cur]] += rightcur - mid - 1
leftcur += 1
cur += 1
else:
pos[cur] = temp[rightcur]
cur += 1
rightcur += 1
while leftcur <= mid:
pos[cur] = temp[leftcur]
res[pos[cur]] += end - mid
cur += 1
leftcur += 1
while rightcur <= end:
pos[cur] = temp[rightcur]
cur += 1
rightcur += 1
def mergeSort(arr, pos, res, start, end):
if start < end:
mid = (start + end)/2
mergeSort(arr, pos, res, start, mid)
mergeSort(arr, pos, res, mid+1, end)
mergeList(arr, pos, res, start, mid, end)
def printResult(arr, res):
print
for i in range(0, len(arr)):
print arr[i], '->', res[i]
if __name__ == '__main__':
inp = input('enter elements separated by ,\n')
inp = list(inp)
res = [0]*len(inp)
pos = [ind for ind, v in enumerate(inp)]
mergeSort(inp, pos, res, 0, len(inp)-1)
printResult(inp, res)
被Minitest视为实际值,而期望值为1
我不确定为什么cart.line_items.size
等于B.假设您对开发服务器和psql的观察是正确的,可能与您的测试条件设置方式有关。如果您在添加订单项的代码之前添加cart.line_items.size
会发生什么情况呢?
assert_equal 0, cart.line_items.size