使用Rails进行敏捷Web开发:找不到id = 1的产品

时间:2012-05-25 20:47:19

标签: ruby-on-rails ruby testunit

我对line_item模型的销毁单元测试失败,并显示错误“无法找到ID为1的产品”。似乎Rails无法破坏我的line_item,因为它从数据库中获取它时会抛出异常。这是我的LineItem模型:

class LineItem < ActiveRecord::Base
  belongs_to :product
  belongs_to :cart

  def total_price
    product.price * quantity
  end
end

以下是测试套件:

require 'test_helper'

class LineItemsControllerTest < ActionController::TestCase
  setup do
    @line_item = line_items(:one)
    Rails.logger.debug(@line_item.to_yaml)
    Rails.logger.debug(Product.all.to_yaml)
  end

  test "should get index" do
    get :index
    assert_response :success
    assert_not_nil assigns(:line_items)
  end

  test "should get new" do
    get :new
    assert_response :success
  end

  test "should create line_item" do
    assert_difference('LineItem.count') do
      post :create, product_id: products(:ruby).id
    end

    assert_redirected_to cart_path(assigns(:line_item).cart)
  end

  test "should show line_item" do
    get :show, id: @line_item
    assert_response :success
  end

  test "should get edit" do
    get :edit, id: @line_item
    assert_response :success
  end

  test "should update line_item" do
    put :update, id: @line_item, line_item: @line_item.attributes
    assert_redirected_to line_item_path(assigns(:line_item))
  end

  test "should destroy line_item" do
    Rails.logger.debug "Breaking!"
    assert_difference('LineItem.count', -1) do
      delete :destroy, id: @line_item
    end

    assert_redirected_to cart_path(path)
  end
end

以下是我记录的部分:

    Breaking!
  [1m[35m (0.1ms)[0m  SELECT COUNT(*) FROM "line_items" 
Processing by LineItemsController#destroy as HTML
  Parameters: {"id"=>"980190962"}
  [1m[36mLineItem Load (0.1ms)[0m  [1mSELECT "line_items".* FROM "line_items" WHERE "line_items"."id" = ? LIMIT 1[0m  [["id", "980190962"]]
  [1m[35mProduct Load (0.1ms)[0m  SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT 1  [["id", 1]]
Completed 500 Internal Server Error in 3ms
  [1m[36m (0.1ms)[0m  [1mrollback transaction[0m
  [1m[35m (0.1ms)[0m  begin transaction
  [1m[36mLineItem Load (0.1ms)[0m  [1mSELECT "line_items".* FROM "line_items" WHERE "line_items"."id" = ? LIMIT 1[0m  [["id", 980190962]]
--- !ruby/object:LineItem
attributes:
  id: 980190962
  product_id: 1
  cart_id: 1
  created_at: 2012-05-25 20:37:17.000000000 Z
  updated_at: 2012-05-25 20:37:17.000000000 Z
  quantity: 1
  product_price: 

  [1m[35mProduct Load (0.2ms)[0m  SELECT "products".* FROM "products" 
---
- !ruby/object:Product
  attributes:
    id: 207281424
    title: Programming Ruby 1.9
    description: Ruby is the fastest growing and most exciting dynamic language out
      there.  If you need to get working programs delivered fast, you should add Ruby
      to your toolbox.
    image_url: ruby.png
    price: 49.5
    created_at: 2012-05-25 20:37:17.000000000 Z
    updated_at: 2012-05-25 20:37:17.000000000 Z  

谢谢!

编辑:这是产品型号:

class Product < ActiveRecord::Base
  has_many :line_items

  before_destroy :ensure_not_referenced_by_any_line_item

  # Validation
  validates :title, :description, :image_url, presence: true
  validates :title, length: {
    minimum: 10,
    message: "must be at least %{count} characters long"
  }
  validates :price, numericality: { greater_than_or_equal_to: 0.01 }
  validates :title, uniqueness: true
  validates :image_url, allow_blank: true, format: {
    with: %r{\.(gif|jpg|png)$}i,
    message: 'must be a URL for GIF, JPG or PNG image.'
  }

  private

  def ensure_not_referenced_by_any_line_item
    if line_items.empty?
      return true
    else
      errors.add :base, 'Line items present'
      return false
    end
  end
end

1 个答案:

答案 0 :(得分:1)

这是工厂普遍受到铁路社区固定装置青睐的原因之一。夹具不会自动加载它们的关联并因此而易于变脆。您的fixture的product_id为1,但该产品不存在。

我不确定如何解决您的具体问题,但我建议您:

  1. 在测试中创建ID = 1的产品。
  2. 创建id = 1的产品夹具并将其加载到您的设置
  3. 切换到工厂(最好是这个)
  4. 修改

    如上所述here,您还可以使用标签引用进行关联。因此,如果您有一个名为“tv”的产品夹具,您可以删除line_item fixture的product_id字段并将其替换为product: tv