【问题标题】:rspec controller testing: "expected #count to have changed by -1, but was changed by 0"rspec 控制器测试:“预计 #count 已更改 -1,但已更改 0”
【发布时间】:2016-08-17 16:27:07
【问题描述】:

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

路线

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

控制器

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

规格/工厂

FactoryGirl.define do

  factory :link do

    case_file
    url 'www.google.com'

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

规范/控制器

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

错误信息

$ rspec 规范/控制器/links_controller_spec.rb ...F

失败:

1) LinksController DELETE destroy 删除一个链接 失败/错误: 期望{删除:销毁,id:link.id,case_id:case_file}。 改变(Link, :count).by(-1)

预计 #count 已更改 -1,但已更改为 0 # ./spec/controllers/links_controller_spec.rb:28:in `block (3 levels) in '

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

失败的例子:

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

【问题讨论】:

  • 我正在使用这些 gem:gem 'rspec-rails', '~> 3.0' gem 'should-matchers', '~> 3.1' gem 'factory_girl_rails'

标签: ruby-on-rails testing rspec rspec-rails


【解决方案1】:

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

因此,链接在传递给expect 的块内创建和销毁:计数不变,测试失败。

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

before(:example) { link }

【讨论】:

    【解决方案2】:

    我发现您的回答非常有用。我找到了有关 let 和 let 的差异的更多信息! here。这里的关键是 let 是惰性求值的。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-28
      • 2019-05-29
      • 1970-01-01
      相关资源
      最近更新 更多