2013-01-19 41 views
1

我正在關注敏捷書籍,並且在單元測試中表現不佳。問題是在rake test:functionals期間正在創建兩個對象,而不是一個。我找出了原因,但我無法解決問題。Rails - 停止測試環境與Obj.find()創建新的對象?

下面是相關代碼:

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 

正常 在開發環境中,current_cart會當會話[:cart_id]已經有購物車時,不會創建另一個購物車。但在測試環境中,只需運行Cart.find(會話[: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 
+0

你爲什麼不希望它這樣做? – sevenseacat

+0

它未通過測試。我可以對2個更新項目進行測試檢查,但似乎有點不清楚,每次調用Cart.new時,假定的函數總是創建兩個新的cart對象。我如何才能在測試環境中創建單個對象? – Xiv

+1

您可能必須發佈您的測試,因爲不應創建兩個購物車。 – sevenseacat

回答

1

我沒有看到任何會使測試行爲不同的東西,但是你的代碼對我來說看起來不對。 對於每個進入的請求,您的before_filter都會加載現有購物車,並在不存在的情況下創建一個新購物車。

您之前過濾器運行後,該操作將運行,這造成不檢查一個是否存在一個車,所以第二臺車是創建

無論你的before_filter和你創造的行動正在創造一個購物車。之前的過濾器首先運行並創建一個,然後創建操作運行並(不檢查購物車的存在)創建另一個。

我不確定爲什麼你有一個create行動,如果在任何時候都爲你創建購物車。您可以跳過創建操作的過濾器,也可以更改創建操作,以便它使用由該過濾器創建的購物車(儘管這會導致創建操作僅僅是更新操作,這會有點奇怪)

+0

嗯,你能解釋爲什麼** before_filter後運行'Cart.create'動作嗎?我的理解是'Cart.create'首先運行,然後'before_filter'運行在頁面上,這應該檢測到購物車已經存在?這是因爲'Cart.create'是直接從運行'post:create,cart:{}'的測試執行的? – Xiv

+0

before_filter總是在動作之前運行(因此名稱)。 after_filter在該動作之後運行。 –

0

測試,這可能不會如重定向遵循這些類型的測試正確地創建2臺車。其他測試,單獨測試,以及在測試中設置時不知道會話變量。然而,這是在看到測試之前編寫的。

您使用的是固定裝置嗎?也許購物車已經加載。嘗試將pry添加到您的gem文件。然後在您的測試中,將調試語句放入binding.pry,您將進入測試控制檯,並執行Cart.count以查看存在多少個購物車。

+0

有沒有什麼辦法可以讓測試環境選擇已經存在的購物車? – Xiv