使用Rails的敏捷Web开发4:line_items_controller_test.rb中的Update操作的MiniTest错误

时间:2014-09-20 20:56:48

标签: ruby-on-rails ruby ruby-on-rails-4 fixtures minitest

我是一名初学者,通过使用Rails 4进行敏捷Web开发,我们(读者)构建了一个购物车风格的演示应用程序。因此,主要的REST资源是1)产品,2)推车和3)订单项。这是我在学习Rails的过程中的第二个演示/示例应用程序,到目前为止,一切看起来都是直截了当的,除了我在测试中的 update 行动中一直出现错误物品控制器。我不确定它是否与测试本身,实际控制器动作和/或我的灯具设置有关。 (我第一次使用"内置" MiniTest和灯具;之前的示例应用我使用了RSpec和FactoryGirl。)

错误(不是失败)我看起来像这样:

Finished tests in 0.936959s, 26.6821 tests/s, 56.5660 assertions/s.

  1) Error:
LineItemsControllerTest#test_should_update_line_item:
ActionController::ActionControllerError: Cannot redirect to nil!
    app/controllers/line_items_controller.rb:54:in `block (2 levels) in update'
    app/controllers/line_items_controller.rb:52:in `update'
    test/controllers/line_items_controller_test.rb:38:in `block in <class:LineItemsControllerTest>'

25 tests, 53 assertions, 0 failures, 1 errors, 0 skips

我不清楚为什么我会重定向到零。路径不好吗?或者它是路径末端的对象?和/或&#34;其他&#34;?我不容易在控制器本身看到任何看起来像问题的东西(无论如何,我已经包含下面的代码),所以我怀疑它与测试文件或灯具设置有关。我已经尝试过填写各种“假人”。 (例如,product_id: 55)和&#39;引用&#39; (例如,product_id: products(:ruby).id)line_items.yml灯具中的值没有成功。

我还在控制器测试设置中尝试了不同的内容,例如引用订单项所属的其他灯具类型(产品和购物车)中的特定灯具ID(与上述相同的想法) )。我也尝试过以多种方式编辑更新测试,包括尝试重定向到订单项的购物车而不是line_items_path,例如:

assert_redirected_to cart_path(assigns(:line_item).cart)

......而不是......

assert_redirected_to line_item_path(assigns(:line_item))

还尝试了定义的变体:line_item,我将其作为更新的对象,例如:

patch :update, id: @line_item, line_item: { product_id: products(:ruby).id }

......而不是......

patch :update, id: @line_item, line_item: { product_id: @line_item.product_id }

我认为相关的代码包含在下面。非常感谢任何帮助!

line_items_controller.rb

class LineItemsController < ApplicationController
  include CurrentCart
  before_action :set_cart, only: [:create]
  before_action :set_line_item, only: [:show, :edit, :update, :destroy]


  # GET /line_items
  # GET /line_items.json
  def index
    @line_items = LineItem.all
  end

  # GET /line_items/1
  # GET /line_items/1.json
  def show
  end

  # GET /line_items/new
  def new
    @line_item = LineItem.new
  end

  # GET /line_items/1/edit
  def edit
  end

  # POST /line_items
  # POST /line_items.json
  def create
    product = Product.find(params[:product_id])
    @line_item = @cart.add_product(product.id)

    respond_to do |format|
      if @line_item.save
        format.html { redirect_to @line_item.cart,
          notice: 'Line item was successfully created.' }
        format.json { render action: 'show',
          status: :created, location: @line_item }
      else
        format.html { render action: 'new' }
        format.json { render json: @line_item.errors,
          status: :unprocessable_entity }
      end
    end

    session[:count] = nil
  end

  # PATCH/PUT /line_items/1
  # PATCH/PUT /line_items/1.json
  def update
    respond_to do |format|
      if @line_item.update(line_item_params)
        format.html { redirect_to @line_item.cart,
          notice: 'Line item was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @line_item.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /line_items/1
  # DELETE /line_items/1.json
  def destroy
    @line_item.destroy
    respond_to do |format|
      format.html { redirect_to line_items_url }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_line_item
      @line_item = LineItem.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def line_item_params
      params.require(:line_item).permit(:product_id)
    end
end

line_items_controller_test.rb

require 'test_helper'

class LineItemsControllerTest < ActionController::TestCase
  setup do
    @line_item = line_items(:one)
  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
    patch :update, id: @line_item, line_item: { product_id: @line_item.product_id }
    assert_redirected_to line_item_path(assigns(:line_item))
  end

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

    assert_redirected_to line_items_path
  end
end

line_items.yml

one:
  product_id: #Trying values here doesn't seem to help.
  cart_id: #Trying values here doesn't seem to help.

two:
  product_id: 
  cart_id: 

products.yml

one:
  title: MyString
  description: MyText
  image_url: MyString
  price: 9.99

two:
  title: MyString
  description: MyText
  image_url: MyString
  price: 9.99

ruby:
  title:        Programming Ruby 1.9
  description:
    Ruby is the fastest growing and most exicting dynamic
    language out there. If you need to get working programs
    delivered fast, you should add Ruby to your toolbox.
  price:        49.50
  image_url:    ruby.png

three:
  title: MyString
  description: MyText
  image_url: MyString
  price: 9.99  

carts.yml

one: {}
# column: value
#
two: {}
#  column: value

2 个答案:

答案 0 :(得分:1)

line_items_controller.rb中,您使用Rails资源表示法重定向回购物车页面。有问题的订单项是:one,其中没有关联的购物车。尝试通过修改line_item.yml来分配一个,如下所示:

one:
  product: one
  cart: one

认为 Rails应该足够聪明,分别知道这些作业需要ProductCart,但如果没有,您可以尝试使用更具描述性的内容/固定装置的唯一标签::cart_one:product_one甚至:joes_cart:bobs_cart等。

答案 1 :(得分:0)

您的订单项在line_items.yml中没有ID。像这样做

<强> line_item.yml

one:
  id: 1
  product_id: #Trying values here doesn't seem to help.
  cart_id: #Trying values here doesn't seem to help.

two:
  id: 2
  product_id: 
  cart_id: 

您还尝试在测试中传递整个对象而不是id。只需传递id:

patch :update, id: @line_item.id, line_item: { product_id: @line_item.product_id }

你不应该试图发布整个对象。发布对象ID