Ruby on rails 3.1 Rspec+;设计+;工厂女孩测试协会

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

我是Rspec的新手,正在将代码库从Rails3.0.x迁移到Rails3.1.x,同时添加测试。我能够让基本的控制器测试正常工作,但在开始集成Desive之后,我开始遇到问题。具体来说,我有一个名为
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