RSpec控制器测试的实体模型和存根



我正在用RSpec在Viewings模型的控制器上测试create方法。我正在尝试创建一个模拟查看模型,以最大限度地减少对数据库的调用,剔除它的新方法和保存方法,并返回适当的值来测试我的控制器的逻辑是否工作:

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

问题是,即使我根据所处的测试将save截断为返回true或false,但它总是返回一个查看对象,这让我相信截断不起作用,控制器将我的模拟对象视为真实对象,在我调用.save时进行数据库调用。我需要使用viewing以外的类来截断该方法吗?我应该只调用viewing.stub而不是viewing.any_instance吗?事实上,我认为打字可能回答了我自己的问题,但我仍然想听听任何人对这个问题的看法。

不能同时使用

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

最新更新