Rails 控制器(集成?)测试有问题

Trouble with Rails controller (integration?) test

我正在制作我的第一个 Rails 应用程序,所以这可能是基本的。

在我的用户配置文件中,我想让用户添加标题和描述。我将它们设为 User 模型的属性并将其添加到 routes.rb:

  resources :users do
    member do
      post 'update_description'
    end
  end

相同的方法(尚未编写)将处理这两个属性。为了实践 TDD,我想编写一个测试来简单地表明,如果用户提交了一个标题,那么控制器会将其保存到数据库中。我认为那将是一个集成测试,但我找不到正确的路径。 ( 应该 它是一个集成测试吗?)但是后来,通过研究,我设法在相关的控制器测试文件中编写了一个有效的 post 语句。这是控制器测试:

  test "profile submits new title and description successfully" do
    log_in_as(@user)
    get :show, id: @user
    assert_nil @user.title
    post :update_description, id: @user, params: { title: "Lorem ipsum" }
    # Next:
    # @admin.reload.title
    # assert @admin.title == "Lorem ipsum"
    # assert_template 'users/show'
    # Etc.

  end

这会引发以下错误:

ERROR["test_profile_submits_new_title_and_description_successfully", UsersControllerTest, 2017-10-22 21:42:52 -0400]
 test_profile_submits_new_title_and_description_successfully#UsersControllerTest (1508722972.17s)
ActionView::MissingTemplate:         ActionView::MissingTemplate: Missing template users/update_description, application/update_description with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}. Searched in:
          * "/var/lib/gems/2.3.0/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates"
          * "/home/globewalldesk/startthis/app/views"
          * "/var/lib/gems/2.3.0/gems/web-console-2.0.0.beta3/app/views"

            test/controllers/users_controller_test.rb:83:in `block in <class:UsersControllerTest>'
        test/controllers/users_controller_test.rb:83:in `block in <class:UsersControllerTest>'

我了解到这意味着 Rails 正在寻找一个视图文件但找不到,但我不明白为什么 post :update_description 让它寻找一个视图...我认为它会在没有视图的情况下发布信息(我有一条类似的路线,在没有视图的情况下以相同的方式工作)。 update_description 方法在 Users 控制器中。我做了很多研究,但我无法弄清楚我做错了什么。帮助! TIA.

您编写测试的方式看起来像是集成测试。但我个人会建议编写系统测试。因为我看到你创建了一个 update_descriptionmember 路由只是为了更新 User 对象?那不是必需的 - 您的 User 资源已经具有 editupdate 操作,因此您可以删除该成员路由。

集成测试用于检查工作流程以及应用程序不同部分的交互方式。虽然系统检查用于用户交互 - 基本上您检查用户会在其浏览器中执行和查看的内容。此外,在我看来,用这种技术编写测试(至少在这个级别)要简单得多。

因此您的系统测试将如下所示:

setup do
  log_in_as(@user) // or what ever code to visit login page and login user
end

test "profile submits new title successfully" do
  visit edit_user_path

  fill_in "Title", with: "Lorem ipsum"

  click_on "Save"

  assert_response :redirect
  follow_redirect!
  assert_select "Title", text: "Lorem ipsum"
end

这假设在用户提交表单后,应用重定向到 user_path(@user)(显示页面)。

集成测试看起来像:

test "profile submits new title successfully" do
  log_in_as(@user) // or what ever code to login user
  get "/user/#{@user.id}/edit"
  assert_response :success

  updated_title = "Lorem ipsum"

  patch :update, user: { id: @user.id, title: updated_title }

  assert_response :redirect
  follow_redirect!
  assert_response :success
  assert_select "Title", text: "Lorem ipsum"
end

注意 - 我没有对此进行测试,我使用 Capybara 和其他工具,但没有使用 Minitest。但在这个简单的情况下,我认为这应该可行。

如果您还没有这样做,请检查 docs..