2015-11-26 91 views
0

我想弄清楚測試我的控制器的邏輯。正如你在我的控制器中看到的那樣,如果通過電話號碼找到客戶,它應該呈現客戶展示頁面,並且如果客戶沒有通過電話號碼找到,那麼它應該呈現創建頁面。Rspec測試控制器動作創建邏輯

我正在使用rspec和factorygirl。

我的思考過程是建立一個客戶,爲其分配一個特定的ID:999999和電話號碼。

然後做一個帖子:使用相同的電話號碼爲客戶創建。這應該有響應返回作爲客戶/ ID。

當我的代碼通過測試時,當我更改帖子:創建客戶電話號碼時,它仍然通過。我不知道我做錯了什麼,但看起來不對。

控制器:

def create   
    if @customer = Customer.find_by(phone: customer_params[:phone]) 
    redirect_to @customer 
    else 
    @customer = Customer.new(customer_params) 
    if @customer.save 
     redirect_to @customer, notice: "Customer was successfully saved" 
    else 
     render 'new', notice: "Customer was unsuccessfully saved" 
    end 
    end 
end 

控制器規格#1(通過):

it "redirects to the #show/id path if it is an existing customer" do 
    customer = build(:customer) 
    customer[:id] = 999999 
    customer[:phone] = "999" 

    post :create, customer: attributes_for(:customer, phone: "999")    
    expect(response).to redirect_to(:action => :show, :id => assigns(:customer).id) 
end 

控制器規格#2(改後:創造客戶電話)(通過):

it "redirects to the #show/id path if it is an existing customer" do 
    customer = build(:customer) 
    customer[:id] = 99999 
    customer[:phone] = "999" 

    post :create, customer: attributes_for(:customer, phone: "939") 
    expect(response).to redirect_to(:action => :show, :id => assigns(:customer).id) 
end 

回答

0

在這兩種情況下,當找到客戶或創建新客戶時,response將爲redirect_to這就是爲什麼你的測試通過。請注意,由於您在測試中使用的是build,因此這不會將客戶保存在數據庫中,因此您的測試始終會創建一個新的customer,Customer.find_by(phone: customer_params[:phone])始終評估爲nil

測試create操作的最佳方法是比較請求前後的Customer實例的計數。以下是你如何改進你的測試。

let(:customer) { FactoryGirl.create(:customer, phone: '999') } 

context 'user not found by phone' do 
    it 'creates a new customer' do 
    expect{ 
     post :create, customer: attributes_for(:customer, phone: "999") 
    }.to change(Customer, :count).by 1 
    end 

    it 'redirects to the customer path' do 
    post :create, customer: attributes_for(:customer, phone: "999") 

    customer = Customer.last 
    expect(response).to redirect_to(customer) 

    #this is another differentiator between the case where a customer is 
    #found and when one is created 
    expect(flash[:notice).to eq "Customer was successfully saved" 
    end 
end 

context 'user not found by phone' do 
    before(:each) do 
    #here we create the customer before each test in this context 
    customer 
    end 

    it 'does not create a new customer' do 
    expect{ 
     post :create, customer: attributes_for(:customer, phone: customer.phone) 
    }.not_to change(Customer, :count) 
    end 

    it 'redirects to the customer path' do 
    post :create, customer: attributes_for(:customer, phone: customer.phone) 

    customer = Customer.last 
    expect(response).to redirect_to(customer) 

    #this is another differentiator between the case where a customer is 
    #found and when one is created 
    expect(flash[:notice).to be_nil 
    end 
end