【问题标题】:Rspec testing nested destroy action for follows modelRspec 测试跟随模型的嵌套破坏动作
【发布时间】:2015-05-09 12:25:27
【问题描述】:

我已经研究并看到了一个类似的问题 (Rspec: Testing nested destroy action),但无法找到适合我的解决方案。在我正在开发的应用程序中,我们有一个文章模型,用户可以关注文章。

我已经使用acts_as_follower gem 来实现这一点,所以文章模型有一个'followers' 方法,它返回和关注该文章的用户数组。

以下是相关代码:

follows_controller

class FollowsController < ApplicationController
  def create
    @article = Article.find(params[:article_id])
    current_user.follow(@article)
    redirect_to @article
  end

  def destroy
    @article = Article.find(params[:article_id])    
    current_user.stop_following(@article)
    redirect_to @article
  end
end

routes.rb

    get '/articles/:id/history', to: 'articles#history', as: :articles_history
  post '/articles/:id/undo', to: 'articles#undo', as: :undo
  resources :articles do
    resources :follows, :only => [:create, :destroy]
  end

schema.rb

create_table "follows", force: :cascade do |t|
    t.integer  "followable_id",                   null: false
    t.string   "followable_type",                 null: false
    t.integer  "follower_id",                     null: false
    t.string   "follower_type",                   null: false
    t.boolean  "blocked",         default: false, null: false
    t.datetime "created_at"
    t.datetime "updated_at"
  end

spec/controllers/follows_controller_spec.rb 根据@Peter 下面的评论更新

  describe '#DELETE destroy' do
it 'deletes a follow' do
  @article = FactoryGirl.create(:article)
  follow = FactoryGirl.create(:follow, followable_id: @article.id)
  # Also, test if the action really deletes a comment.
  expect{delete :destroy, id: follow.id, article_id: @article.id}.
  to change{@article.followers.count}.by(-1)
end

结束

耙路线:

article_follows POST   /articles/:article_id/follows(.:format)          follows#create
article_follow DELETE /articles/:article_id/follows/:id(.:format)      follows#destroy

这是我在运行测试时遇到的错误:

失败:

1) FollowsController#DELETE destroy deletes a follow
     Failure/Error: expect{delete :destroy, id: follow.id, followable_id: @article.id}.
     ActionController::UrlGenerationError:
       No route matches {:action=>"destroy", :controller=>"follows", :followable_id=>"2", :id=>"2"}

根据@PeterAlfvin 的以下建议添加工厂和新错误:

这是我的工厂:

FactoryGirl.define do
  factory :follow do |f|
    f.follower_id 1
    f.followable_id 1
    f.followable_type "Article"
    f.follower_type "User"
  end
end

这是当前的错误:

  1) FollowsController#DELETE destroy deletes a follow
     Failure/Error: expect{delete :destroy, id: follow.id, article_id: @article.id}.
     NoMethodError:
       undefined method `stop_following' for nil:NilClass
     # ./app/controllers/follows_controller.rb:10:in `destroy'
     # ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/implicit_render.rb:4:in `send_action'
     # ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/abstract_controller/base.rb:198:in `process_action'
     # ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/rendering.rb:10:in `process_action'
     # ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/abstract_controller/callbacks.rb:20:in `block in process_action'
     # ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:117:in `call'
     # ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:117:in `call'
     # ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:555:in `block (2 levels) in compile'
     # ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
     # ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
     # ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:92:in `_run_callbacks'
     # ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:776:in `_run_process_action_callbacks'
     # ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:81:in `run_callbacks'
     # ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/abstract_controller/callbacks.rb:19:in `process_action'
     # ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/rescue.rb:29:in `process_action'
     # ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'
     # ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/notifications.rb:164:in `block in instrument'
     # ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
     # ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/notifications.rb:164:in `instrument'
     # ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/instrumentation.rb:30:in `process_action'
     # ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/params_wrapper.rb:250:in `process_action'
     # ./.bundle/gems/ruby/2.2.0/gems/searchkick-0.8.7/lib/searchkick/logging.rb:107:in `process_action'
     # ./.bundle/gems/ruby/2.2.0/gems/activerecord-4.2.1/lib/active_record/railties/controller_runtime.rb:18:in `process_action'
     # ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/abstract_controller/base.rb:137:in `process'
     # ./.bundle/gems/ruby/2.2.0/gems/actionview-4.2.1/lib/action_view/rendering.rb:30:in `process'
     # ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/test_case.rb:632:in `process'
     # ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/test_case.rb:65:in `process'
     # ./.bundle/gems/ruby/2.2.0/gems/devise-3.4.1/lib/devise/test_helpers.rb:19:in `block in process'
     # ./.bundle/gems/ruby/2.2.0/gems/devise-3.4.1/lib/devise/test_helpers.rb:72:in `catch'
     # ./.bundle/gems/ruby/2.2.0/gems/devise-3.4.1/lib/devise/test_helpers.rb:72:in `_catch_warden'
     # ./.bundle/gems/ruby/2.2.0/gems/devise-3.4.1/lib/devise/test_helpers.rb:19:in `process'
     # ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/test_case.rb:532:in `delete'
     # ./spec/controllers/follows_controller_spec.rb:22:in `block (4 levels) in <top (required)>'
     # ./spec/controllers/follows_controller_spec.rb:22:in `block (3 levels) in <top (required)>'
     # ./spec/spec_helper.rb:57:in `block (3 levels) in <top (required)>'
     # ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/generic/base.rb:15:in `cleaning'
     # ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/base.rb:92:in `cleaning'
     # ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/configuration.rb:86:in `block (2 levels) in cleaning'
     # ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/configuration.rb:87:in `call'
     # ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/configuration.rb:87:in `cleaning'
     # ./spec/spec_helper.rb:56:in `block (2 levels) in <top (required)>'

【问题讨论】:

  • 你在哪里定义delete_request
  • 我不小心复制粘贴了之前的一个错误。以上更正。
  • 尝试用article_id替换followable_id
  • 更改为:describe '#DELETE destroy' do it 'deletes a follow' do @article = FactoryGirl.create(:article) follow = FactoryGirl.create(:follow, article_id: @article. id) # 另外,测试该操作是否真的删除了评论。期望{删除:销毁,id:follow.id,article_id:@article.id}。更改{@article.followers.count}.by(-1) end end get error: NoMethodError: undefined method `article_id=' for #
  • 编辑了问题以包含 Follows 表的架构。

标签: ruby-on-rails-4 rspec nested-attributes


【解决方案1】:

我认为路由错误确实是由于指定了followable_id 而不是您收到的评论所暗示的article_id。然而,随后的 no method 错误也是由于在工厂调用中进行了该更改。以下是您应该尝试的:

describe '#DELETE destroy' do
  it 'deletes a follow' do
    @article = FactoryGirl.create(:article)
    follow = FactoryGirl.create(:follow, followable_id: @article.id)
    # Test if the action really deletes a follow.
    expect{delete :destroy, id: follow.id, article_id: @article.id}.
    to change{@article.followers.count}.by(-1)
  end
end 

【讨论】:

  • 彼得,谢谢。我已经实现但现在得到一个错误,我认为这表明我没有创建有效的文章对象:nil:NilClass 的未定义方法“stop_following”。 stop_following 是 gem 提供的方法。
  • 不,stop_following 正在被current_user 调用,所以您显然没有登录。
  • 修复了它。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多