2013-08-03 116 views
3

我正在使用RSpec在我的Viewings模型的控制器上測試create方法。我試圖創建一個模擬的觀看模式,以儘量減少對我的數據庫調用,磕碰了其新的保存方法並返回相應的值來測試我的控制器的邏輯是否工作:RSpec控制器測試的模擬模型和存根

describe 'POST #create' do 
    let(:office_listing) { create(:office_listing) } 
    let(:viewing) { mock_model(Viewing).as_null_object } 
···· 
    before do· 
     Viewing.stub(:new).and_return(viewing) 
    end 

    describe 'with valid attributes' do 
     it 'saves the viewing' do· 
     Viewing.any_instance.stub(:save).and_return(true) 
     viewing.should_receive(:save) 
     post :create, office_listing_id: office_listing.id 
     end 
    end 

    describe 'with invalid attributes' do 
     it 'fails and renders a failure message' do 
     Viewing.any_instance.stub(:save).and_return(false) 
     viewing.should_receive(:save) 
     post :create, :office_listing_id => office_listing.id 
     assigns(:failure_message).should_not be_nil 
     end 
    end 
    end 
end 

這裏是我的控制器代碼:

def create 
    @viewing = Viewing.new(params[:viewing]) 
    @viewing.broker = current_broker 
    @viewing.office_listing = params[:office_listing_id] 

    p @viewing.save 

    if @viewing && @viewing.save == true 
     respond_to do |format| 
     format.js 
     format.html { redirect_to root_path } 
     end 
    else 
     respond_to do |format| 
     @failure_message = "Unable to create viewing." 
     format.js 
     format.html { redirect_to root_path } 
     end 
    end 
    end 
end 

的問題是,即使我已經掐滅保存返回true或false取決於測試我在,它總是返回視覺對象,這使我相信,磕碰ISN沒有工作,控制器正在將我的模擬對象當作一個真正的對象,在我調用.save時進行數據庫調用。我是否需要使用除查看以外的其他類來清除方法?我應該只是調用viewing.stub而不是Viewing.any_instance?其實我認爲打字可能會回答我自己的問題,但我仍然希望聽到任何人對此問題的看法。

回答

3

您不能同時使用

Viewing.any_instance.stub(:save) 

viewing.should_receive(:save) 

第一種是使用控制流,而第二個用於測試的東西。

你應該這樣做:

let!(:viewing) { Viewing.new } # no lazy load, executed right away, no need to mock 

def action 
    post :create, office_listing_id: office_listing.id 
end 

before do 
    Viewing.stub(:new).and_return(viewing) 
end 

it "calls save" do 
    expect(viewing).to receive(:save).and_return(true) 
    action 
end