【问题标题】:Why is this Rails Minitest assert_equal failing with these Expected and Actual values?为什么这个 Rails Minitest assert_equal 因这些预期值和实际值而失败?
【发布时间】:2018-01-04 12:56:36
【问题描述】:

我有;

  • 一个购物车有_many Line_items。
  • Line_item 属于购物车。
  • 一个产品有_many Line_items。
  • Line_item 属于产品。

在发布到 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 item。

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 进行敏捷 Web 开发的第 10 章末尾定义的额外“游戏时间”任务。

【问题讨论】:

    标签: ruby-on-rails minitest


    【解决方案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"
    

    【讨论】:

      【解决方案2】:

      针对 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-09-07
        • 2010-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-29
        • 1970-01-01
        • 2020-10-09
        相关资源
        最近更新 更多