gpt4 book ai didi

ruby-on-rails-3.1 - Rspec + Devise + Factory Girl 测试与协会

转载 作者:行者123 更新时间:2023-12-04 05:57:09 26 4
gpt4 key购买 nike

我对 Rspec 非常陌生,正在将代码库从 Rails 3.0.x 迁移到 Rails 3.1.x 并同时添加测试。我能够进行基本的 Controller 测试,但是在开始集成 Devise 之后,我开始遇到问题。具体来说,我有一个名为 User 的设计对象属于 Company ,以及 Company有很多Communities .我正在尝试为 Communities 编写测试 Controller ,并且当尝试通过关联引用(例如 controller.current_user.communities )时,我无法引用我创建的 Factory 对象。当我尝试测试时,出现以下(或类似)错误:
No route matches {:id=>nil, :controller=>"communities", :action=>"edit"}
我确定我遗漏了一些与 Rspec/Factory_Girl 相关的基本内容,但任何帮助将不胜感激。

用于测试 edit 的设置示例为 Communities 采取行动如下:

/config/routes.rb

Units::Application.routes.draw do

devise_for :users

resources :companies
resources :communities

...

root :to => 'companies#index'

end

/app/models/user.rb
class User < ActiveRecord::Base
belongs_to :company
has_many :communities, :through => :company
...
end

/app/models/company.rb
class Company < ActiveRecord::Base
has_many :users
has_many :communities
...
end

/app/models/community.rb
class Community < ActiveRecord::Base
belongs_to :company
...
end

/spec/controllers/communities_controller_spec.rb
require 'spec_helper'

describe CommunitiesController do
render_views
login_user
...
context "GET #edit" do
before(:each) do
@company = controller.current_user.company
@community = controller.current_user.communities.new[Factory.build(:community, :company => @company)]
controller.current_user.company.communities.should_receive(:find).with(:company => @company)
end

it "should be successful" do
get :edit, :id => @community
response.should be_successful
end

it "should find a specific community" do
get :edit, :id => @community
assigns(:community).should eq(@community)
end
end
...
end

/app/controllers/communities_controller.rb
class CommunitiesController < ApplicationController
...
def edit
@community = current_user.communities.find(params[:id])
end
...
end

/spec/support/controller_macros.rb
module ControllerMacros
def login_user
before(:each) do
@request.env["devise.mapping"] = Devise.mappings[:user]
company = Factory.create(:company)
user = Factory.create(:user, :company => company)
# user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the confirmable module
sign_in user
end
end
end

最佳答案

错误:“没有路由匹配 {:id=>nil, :controller=>"communities", :action=>"edit"}” 是你 before(:each) 块中的行的结果,内容如下:

@community = controller.current_user.communities.new[Factory.build(:community, :company => @company)]

请注意,Factory.build 与 Factory.create 不同。 Build 创建对象的一个​​新实例,但实际上并没有将它保存到数据库中。此外,您正在使用这个新的 Factory 实例创建一个新的社区实例,而不保存它。我建议按如下方式创建您的社区:
   @community = Factory.create(:community, :company => @company)

您稍后将使用这个 @community 变量,并将其在您的测试中传递给“get”方法:
get :edit, :id => @community

因为社区没有被保存,所以它没有 ID。它只存在于内存中。此外,发送获取@community 对象的 id 会更正确(在您更新 Factory.build 以读取 Factory.create 之后):
get :edit, :id => @community.id

其次,你的关联似乎与你的 Controller 中的逻辑不一致:
controller.current_user.company.communities.should_receive(:find).with(:company => @company)

在您的 Controller 中,您通过链接 current_user.communities 而不是 current_user.company.communities 来查找社区。我建议删除此测试,因为您想测试结果,而不是实现。这使得测试太脆弱,无法更改代码。

最后,我想提一下您的测试中有多个断言。您在 before(:each) 中断言:
controller.current_user.company.communities.should_receive(:find).with(:company => @company)

这是在它下面的每个嵌套测试中运行的,因此每个测试都检查两个条件。这应该更好地隔离。我建议将此代码移至其自己的测试块,并将其移出 before 方法:
it "should find communities" do
controller.current_user.company.communities.should_receive(:find).with(:company => @company)
end

但是,正如我上面提到的,我不认为这个测试是一个好主意,因为它与您正在测试的实现紧密结合。

关于ruby-on-rails-3.1 - Rspec + Devise + Factory Girl 测试与协会,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9381369/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com