Ruby on rails 3.1 Rspec+;设计+;工厂女孩测试协会
我是Rspec的新手,正在将代码库从Rails3.0.x迁移到Rails3.1.x,同时添加测试。我能够让基本的控制器测试正常工作,但在开始集成Desive之后,我开始遇到问题。具体来说,我有一个名为Ruby on rails 3.1 Rspec+;设计+;工厂女孩测试协会,ruby-on-rails-3.1,rspec,factory-bot,Ruby On Rails 3.1,Rspec,Factory Bot,我是Rspec的新手,正在将代码库从Rails3.0.x迁移到Rails3.1.x,同时添加测试。我能够让基本的控制器测试正常工作,但在开始集成Desive之后,我开始遇到问题。具体来说,我有一个名为User的设计对象,它属于公司,而公司有许多社区。我正在尝试为社区控制器编写测试,当尝试通过关联引用时(例如控制器.current\u user.Communities),我无法引用我创建的Factory对象。当我尝试测试时,会出现以下(或类似)错误: 没有路由匹配{:id=>nil,:contro
User
的设计对象,它属于公司
,而公司
有许多社区
。我正在尝试为社区
控制器编写测试,当尝试通过关联引用时(例如控制器.current\u user.Communities
),我无法引用我创建的Factory对象。当我尝试测试时,会出现以下(或类似)错误:
没有路由匹配{:id=>nil,:controller=>“communities”,:action=>“edit”}
我确信我遗漏了一些与Rspec/Factory\u Girl相关的基本信息,但如果有任何帮助,我将不胜感激。
测试
社区
的编辑
操作的设置示例如下:
@community = Factory.create(:community, :company => @company)
/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/controllers/communities\u controller.rb
class CommunitiesController < ApplicationController
...
def edit
@community = current_user.communities.find(params[:id])
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会创建对象的新实例,但实际上不会将其保存到数据库中。此外,您正在使用这个新的工厂实例创建一个新的社区实例,而不保存它。我建议您创建以下社区:
@community = Factory.create(:community, :company => @company)
您稍后将获取这个@community变量,并将其在测试中传递给“get”方法:
因为社区没有保存,所以它没有ID。它只存在于内存中。此外,更正确的做法是发送并获取@community对象的id(在您将Factory.build更新为读取Factory.create之后):
其次,您的关联似乎与控制器联机中的逻辑不一致:
controller.current_user.company.communities.should_receive(:find).with(:company => @company)
在控制器中,通过链接当前_user.communities而不是当前_user.company.communities来查找社区。我建议删除此测试,因为您希望测试结果,而不是实现。这使得测试过于脆弱,无法编写更改代码
最后,我想提到的是,您的测试中有多个断言。您在您的before(:each)中声明:
这是在它下面的每个嵌套测试中运行的,因此每个测试都检查两个条件。这应该是更好的隔离。我建议将此代码移到它自己的测试块中,并将其移出before方法:
it "should find communities" do
controller.current_user.company.communities.should_receive(:find).with(:company => @company)
end
但是,正如我上面提到的,我认为这个测试不是一个好主意,因为它与您正在测试的内容的实现紧密结合。请添加您的
config/routes.rb
您可以在中添加p@community
,它“应该会成功”
section并给我们结果?@farnoy我把p@community
放在那一部分,但它没有改变输出。我仍然收到以下错误:Failure/error:get:edit,:id=>@community ActionController::RoutingError:No路由匹配{:id=>nil,:controller=>“communities”,:action=>“edit”}
你把它放在了\get
调用之前了吗?非常感谢你的清晰解释-这很有意义。此外,避免测试实现而不是输出似乎也是一个好主意;我相应地修改了代码。
@community = Factory.create(:community, :company => @company)
get :edit, :id => @community
get :edit, :id => @community.id
controller.current_user.company.communities.should_receive(:find).with(:company => @company)
controller.current_user.company.communities.should_receive(:find).with(:company => @company)
it "should find communities" do
controller.current_user.company.communities.should_receive(:find).with(:company => @company)
end