【问题标题】:How to call the create action from the controller in RSpec如何从 RSpec 中的控制器调用创建操作
【发布时间】:2023-03-08 12:05:01
【问题描述】:

我有一个控制器创建操作,它创建一个新的博客文章,如果文章保存成功,则运行一个附加方法。

我有一个单独的工厂女孩​​文件,其中包含我要发布的帖子的参数。 FactoryGirl.create 调用 ruby​​ create 方法,而不是我的控制器中的 create 操作。

如何从我的 RSpec 中的控制器调用创建操作?我如何将我的工厂女孩​​factories.rb 文件中的参数发送给它?

posts_controller.rb

def create
  @post = Post.new(params[:post])
  if @post.save
    @post.my_special_method
    redirect_to root_path
  else
    redirect_to new_path
  end
end

spec/requests/post_pages_spec.rb

it "should successfully run my special method" do
  @post = FactoryGirl.create(:post)
  @post.user.different_models.count.should == 1
end

post.rb

def my_special_method
  user = self.user
  special_post = Post.where("group_id IN (?) AND user_id IN (?)", 1, user.id)
  if special_post.count == 10
    DifferentModel.create(user_id: user.id, foo_id: foobar.id)
  end
end   

结束

【问题讨论】:

  • 我认为您对 FactoryGirl 的用途有点困惑……它用于在数据库中生成数据,而不是用于调用控制器操作。您在post_pages_spec.rb 中描述的内容看起来像是对 Post 模型的单元测试,而不是实际的请求规范。显式调用控制器操作仅在控制器规范中完成,并且是这样完成的:relishapp.com/rspec/rspec-rails/v/2-13/docs/controller-specs
  • 谢谢七海猫。为了清楚起见,我添加了my_special_method 的定义。如您所见,该方法计算已保存在数据库中的special_posts 的数量。我的 rspec 中有一个 before 块,它创建了 9 个先前的帖子。我想确保第十个帖子会创建一个新的differentmodel 对象。
  • 这又不是一个请求规范。控制器规范是唯一明确调用控制器操作的规范。
  • 好的,谢谢七海猫。我以为我读过(RailsCasts,Rails 教程),有些人放弃了控制器规范,只用模型和请求规范涵盖了所有内容。这是不好的做法吗?
  • 有些人会这样做,但这并不意味着您只需将控制器测试放在请求规范中。

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


【解决方案1】:

请求规范是集成测试,使用 Capybara 之类的东西以用户可能的方式访问页面并执行操作。您根本不会从请求规范中测试 create 操作。您将访问新项目路径,填写表单,点击提交按钮,然后确认创建了一个对象。看看Railscast on request specs 就是一个很好的例子。

如果您想测试创建操作,请使用控制器规范。结合 FactoryGirl,看起来像这样:

it "creates a post" do
  post_attributes = FactoryGirl.attributes_for(:post)
  post :create, post: post_attributes
  response.should redirect_to(root_path)
  Post.last.some_attribute.should == post_attributes[:some_attribute]
  # more lines like above, or just remove `:id` from
  #   `Post.last.attributes` and compare the hashes.
end

it "displays new on create failure" do
  post :create, post: { some_attribute: "some value that doesn't save" }
  response.should redirect_to(new_post_path)
  flash[:error].should include("some error message")
end

这些是您真正需要的与创作相关的唯一测试。在您的具体示例中,我将添加第三个测试(同样是控制器测试)以确保创建适当的 DifferentModel 记录。

【讨论】:

  • 谢谢吉姆,这太完美了。顺便说一句,我还想测试一个投票动作,到vote_post_path(post, type: "like") 的路径。我该怎么做?我试过post :vote, post: my_post, type: "like",但这给了我No route matches {:post=>"391", :type=>"like", :controller=>"post", :action=>"vote"} rake routes 告诉我它的vote_post POST /posts/:id/vote(.:format)
  • 没关系,想通了。 post :vote, id: my_post.id, type: 'like' 工作正常。再次感谢您的帮助。
猜你喜欢
  • 2017-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多