首页 文章

rspec控制器测试:“预期#count已更改为-1,但已更改为0”

提问于
浏览
1

我无法解决此错误 . 我不确定controller_spec的哪一部分写得错误 . 请帮忙!

Routes

Rails.application.routes.draw do
  resources :cases, only: [:index, :show, :new, :create, :edit, :update] do
    resources :links, only: [:create, :destroy]
  end
end

Controller

class LinksController < ApplicationController

  before_action :prepare_case

  def destroy
    @link = @case_file.links.find(params[:id])
    @link.destroy
    redirect_to case_path(@case_file)
  end

  private

  def prepare_case
    @case_file = CaseFile.find(params[:case_id])
  end
end

spec/factories

FactoryGirl.define do

  factory :link do

    case_file
    url 'www.google.com'

    trait :invalid do
      case_file nil
      url ''
    end
  end
end

spec/controllers

require 'rails_helper'

RSpec.describe LinksController, type: :controller do

  let(:user) { build(:user) }
  before { login_user user }
  #for user log in

  let(:case_file) { create(:case_file) }
  let(:link) { create(:link, case_file: case_file) }

  describe "DELETE destroy" do
    it "deletes a link" do
      expect { delete :destroy, id: link.id , case_id: case_file }.
      to change(Link, :count).by(-1) 
      expect(response).to redirect_to(case_path(case_file))
    end
  end
end

Error Message

$ rspec spec / controllers / links_controller_spec.rb ... F.

失败:

1)LinksController DELETE destroy删除链接失败/错误:expect {delete:destroy,id:link.id,case_id:case_file} . 改变(链接,:计数).by(-1)

预期#count已经改变了-1,但是改为0# . / spec / console / linksscontrol_spec.rb:28:在`block(3 levels)in'

在1.18秒完成(文件加载5.03秒)4个例子,1个失败

失败的例子:

rspec ./spec/controllers/links_controller_spec.rb:27#LinksController DELETE destroy删除链接

2 回答

  • 4

    这是一个经典的错误(虽然我找不到好的复制品) . 当您使用 let 时,rspec仅执行关联的块,在您创建 Link 对象的情况下,第一次引用它时 .

    因此,链接在传递给 expect 的块中被创建和销毁:计数不会更改,测试也会失败 .

    您需要做的就是参考测试前面的 link . 如果您使用 let! 而不是 let ,那么rspec将在示例运行并且您的测试通过之前创建对象,而不是仅在测试中的某处添加随机调用 link . 这和做的一样

    before(:example) { link }
    
  • 1

    我发现你的答案非常有用 . 我发现了有关let和let的差异的更多信息! here . 这里的关键是let是懒惰评估的 .

    在这种情况下,我会使用let!所以你不需要手动调用该方法 .

相关问题