1

我正在关注敏捷书,但我无法让我的单元测试正常运行。问题是在此期间创建了两个对象rake test:functionals而不是一个。我已经确定了原因,但我无法解决问题。

以下是相关代码:

class CartsController < ApplicationController
  def create
    @cart = Cart.new(params[:cart])
    session[:cart_id] = @cart.id

    respond_to do |format|
      if @cart.save
        format.html { redirect_to @cart }
        format.json { render json: @cart, status: :created, location: @cart }
      else
        format.html { render action: "new" }
        format.json { render json: @cart.errors, status: :unprocessable_entity }
      end
    end
  endnormal

当它重定向到@cart 时,它会调用 application_controller,其中包含以下代码:

class ApplicationController < ActionController::Base
  protect_from_forgery
  before_filter :the_cart

  private

    def the_cart
      @cart = current_cart
    end

    def current_cart
      Cart.find(session[:cart_id])
    rescue ActiveRecord::RecordNotFound
      cart = Cart.create
      session[:cart_id] = cart.id
      cart
    end

normal 在开发环境中,当 session[:cart_id] 已经有购物车时,current_cart 不会再创建另一个购物车。但在测试环境中,只需运行 Cart.find(session[:cart_id]) 就会创建一个新的调用新的购物车项目。我该如何解决这个问题,以便 .find 不会每次都为测试环境创建一个新对象?

编辑:这是失败的测试

  test "should create cart" do
    Rails::logger.debug "CREATING CART"
    Rails::logger.debug Cart.all.to_a
    assert_difference('Cart.count') do
      post :create, cart: {  }
      Rails::logger.debug Cart.all.to_a
    end

    assert_redirected_to cart_path(assigns(:cart))
  end
4

2 回答 2

1

我没有看到任何会使测试表现不同的东西,但是您的代码对我来说看起来是错误的。对于传入的每个请求,您before_filter将加载现有的购物车并创建一个新的(如果不存在)。

运行之前的过滤器后,该操作将运行,它创建一个购物车而不检查是否存在,因此创建了第二个购物车

您的 before_filter 和您的 create 操作都在创建购物车。before 过滤器首先运行并创建一个,然后运行 ​​create 操作并(不检查购物车的存在)创建另一个。

create如果在任何时候为您创建了购物车,我不确定您为什么要采取行动。您可以为创建操作跳过该过滤器,或者更改创建操作以使其使用由该过滤器创建的购物车(尽管这会导致创建操作只是一个更新操作,这有点奇怪)

于 2013-01-19T11:51:37.780 回答
0

如果您正在使用请求规范或集成测试,这可能不会创建 2 个购物车,因为在这些类型的测试中正确地遵循了重定向。其他测试,单独测试,我不知道在测试中设置的会话变量。然而,这是在看到测试之前写的。

你在使用固定装置吗?也许购物车已经装好了。尝试添加pry到您的 gem 文件中。然后在您的测试中,放置调试语句的地方binding.pry,您将进入测试控制台,并执行 aCart.count查看存在多少购物车。

于 2013-01-19T11:26:35.940 回答