使用Rspec + FactoryGirl测试嵌套资源的“创建”操作

时间:2013-04-12 14:13:47

标签: ruby-on-rails rspec factory-bot

我在互联网上搜索过很多以及Stackoverflow上的其他类似问题,但是我仍然不确定如何在我的rails应用程序中测试嵌套资源的create方法。

资源路线

resources :projects, :except => [:index, :show] do
      resources :mastertags
end

以下是我要测试的操作:

 def create
    @mastertag =  @project.mastertags.build(params[:mastertag])

    respond_to do |format|
      if @mastertag.save
        format.html { redirect_to project_mastertags_path, notice: 'Mastertag was successfully created.' }
      else
        format.html { render action: "new" }
      end
    end
  end

这是我相应的Rspec测试:

  context "with valid params" do
      it "creates a new Mastertag" do
        project = Project.create! valid_attributes[:project]
        mastertag = Mastertag.create! valid_attributes[:mastertag]
        expect {
          post :create, { project_id: project.id, :mastertag => valid_attributes[:mastertag] }
        }.to change(Mastertag, :count).by(1)
      end
  end

我有一个valid_attributes函数:

  def valid_attributes
      { :project => FactoryGirl.attributes_for(:project_with_researcher), :mastertag => FactoryGirl.attributes_for(:mastertag) }
  end

我收到以下错误:

Failure/Error: post :create, { project_id: project.id, :mastertag => valid_attributes[:mastertag] }
NoMethodError:
undefined method `reflect_on_association' for "5168164534b26179f30000a1":String

我也尝试了几种变体,但似乎没有任何效果。

2 个答案:

答案 0 :(得分:0)

您的FactoryGirl版本的答案会略有改变。

第一个问题是@projet创建在哪里?在其他地方我猜?

您正在创建项目和mastertag,为什么要这样做?

project = Project.create! valid_attributes[:project]
mastertag = Mastertag.create! valid_attributes[:mastertag]

这正是FactoryGirl在您致电Factory(:project)Factory(:mastertag)

时所做的工作

下一个“wat”,就是你在你的规范中创建了一个mastertag。你不要在任何地方使用那个变量。如果不解决您的问题,您的规格看起来会更好:

it "creates a new Mastertag" do
  project = Factory(:project)
  expect {
    post :create, { project_id: project.id, :mastertag => Factory.attributes_for(:mastertag)}
  }.to change(Mastertag, :count).by(1)
end

好的,现在我们已经完成清理规范,让我们看看你的错误。

看起来就在这一行

format.html { redirect_to project_mastertags_path, notice: 'Mastertag was successfully created.' }

此路径需要项目ID。

format.html { redirect_to project_mastertags_path(@project), notice: 'Mastertag was successfully created.' }

答案 1 :(得分:0)

@John Hinnegan的回答绝对正确。我只想补充说,重要的是,要在项目中使用Id,而不仅仅是项目:

有时使用项目可能是显而易见的:在param中,但这不起作用。

使用:

 expect {
      post :create, { project_id: project.id, :mastertag => valid_attributes[:mastertag] }
    }.to change(Mastertag, :count).by(1)

不起作用:

 expect {
      post :create, { project: project.id, :mastertag => valid_attributes[:mastertag] }
    }.to change(Mastertag, :count).by(1)