我正在关注敏捷书籍,我无法让我的单元测试表现得很好。问题是在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
正常 在开发环境中,当session [:cart_id]已经有购物车时,current_cart将不会创建另一个购物车。但是在测试环境中,只需运行Cart.find(session [:cart_id])就可以创建一个新的Cart项目。我如何解决这个问题,以便.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
答案 0 :(得分:1)
我没有看到任何可能使测试行为不同的内容,但您的代码对我来说是错误的。
对于每个请求,before_filter
将加载现有购物车,如果不存在,则创建一个新购物车。
在运行之前的过滤器之后,操作将会运行,这将创建一个购物车而不检查是否存在,因此创建了第二个购物车
您的before_filter和您的创建操作都在创建购物车。先前过滤器首先运行并创建一个,然后运行创建操作并且(不检查购物车的存在)创建另一个。
如果在任何时候为您创建了购物车,我不确定您为何会采取create
行动。您可以跳过该过滤器以进行创建操作,也可以更改创建操作,以便它使用该过滤器创建的购物车(尽管这会导致创建操作只是一个更新操作,这有点奇怪)< / p>
答案 1 :(得分:0)
如果您正在使用请求规范或集成测试,这可能不会创建2个购物车,因为在这些类型的测试中正确遵循重定向。其他测试,单独测试,我在测试中设置时不知道会话变量。这是在看到测试之前编写的。
你在使用灯具吗?也许购物车已经装好了。尝试将pry
添加到您的gem文件中。然后在您的测试中,调试语句放在binding.pry
,您将进入测试控制台,并执行Cart.count
以查看存在多少购物车。