为什么这个Rails Minitest assert_equal失败了这些预期值和实际值?

时间:2018-01-04 12:56:37

标签: ruby-on-rails minitest

我有;

  • 购物车has_many Line_items。
  • Line_item属于购物车。
  • 产品has_many Line_items。
  • Line_item属于产品。

在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_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 "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'任务。

2 个答案:

答案 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