RSpec上的更多错误行为期望更改计数与销毁

时间:2014-02-19 15:16:21

标签: ruby-on-rails ruby rspec

我正在创建一个人们可以创造就业机会的应用程序,但只能破坏他们创造的工作。我知道我的应用程序可以让人们破坏工作,因为我可以手动测试它,但RSpec却落后了。

以下是相关测试:

jobs_controller_spec.rb

require 'spec_helper'

describe JobsController do
  let!(:user) { FactoryGirl.create(:user) }
  let!(:job) { FactoryGirl.create(:job, user: user) }
  let!(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
  let!(:wrong_job) { FactoryGirl.create(:job, user: wrong_user) }

  [...]

  describe "correct user control" do
    before { sign_in user }
    describe "users can only delete their own jobs" do
      it "should not change job count" do
        expect do
          delete :destroy, id: wrong_job.id
        end.to_not change(Job, :count)
      end
    end
    describe "users can delete their own jobs" do
      it "should decrease job count" do
        expect do
          delete :destroy, id: job.id
            end.to change(Job, :count).by(-1)
          end
        end
      end
    end

这是失败的测试:

1) JobsController correct user control users can delete their own jobs should decrease job count
     Failure/Error: expect do
       count should have been changed by -1, but was changed by 0
     # ./spec/controllers/jobs_controller_spec.rb:41:in `block (4 levels) in <top (required)>'

jobs_controller.rb

class JobsController < ApplicationController
  skip_before_action :require_signin, only: [:index, :show]
  skip_before_action :correct_user, only: [:index, :show, :new, :create]
  before_action :set_job, only: [:show, :edit, :update, :destroy]

  [...]

  def destroy
    @job.destroy
    respond_to do |format|
      format.html { redirect_to jobs_url }
      format.json { head :no_content }
    end
  end

  private
    def set_job
      @job = Job.find(params[:id])
    end

  def job_params
    params.require(:job).permit(:title, :org, :internship, :postdate, :filldate, :location, :link, :description)
  end
end

application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_filter :require_signin
  before_filter :correct_user

  include SessionsHelper

  private
    def require_signin
      unless signed_in?
        store_location
        redirect_to signin_url, notice: "Please sign in."
      end
    end

    def correct_user
      @job = current_user.jobs.find_by(id: params[:id])
      redirect_to root_url if @job.nil?
    end
end

佣金路线

Prefix Verb   URI Pattern              Controller#Action
       jobs GET    /jobs(.:format)          jobs#index
            POST   /jobs(.:format)          jobs#create
    new_job GET    /jobs/new(.:format)      jobs#new
   edit_job GET    /jobs/:id/edit(.:format) jobs#edit
        job GET    /jobs/:id(.:format)      jobs#show
            PATCH  /jobs/:id(.:format)      jobs#update
            PUT    /jobs/:id(.:format)      jobs#update
            DELETE /jobs/:id(.:format)      jobs#destroy
[...]

2 个答案:

答案 0 :(得分:1)

正如Peter Alfvin指出的那样,如果控制器规范中存在身份验证,则必须设置会话并将其作为第三个参数传递,例如:

...
let(:some_user) { User.create }

def valid_session
  { user_id: some_user.id }
end

describe "DELETE destroy" do
  it "destroys the requested job" do
    job = Job.create! valid_attributes
    expect {
      delete :destroy, { :id => job.to_param }, valid_session
    }.to change(Job, :count).by(-1)
  end
end

答案 1 :(得分:0)

解决方案是将no_capybara: true传递给sign_in。 Capybara不适用于控制器测试,因此不能使用水豚来管理登录过程。

感谢Patrick Brinich-Langlois的解决方案。