使用 get :edit vs get edit_user_path 进行 rails 集成测试



我正在学习 Hartl 在第 9 章中的练习,并进入了为需要登录用户编写集成测试的部分。

我注意到示例 9.17 (i( 使用

get :edit, id: @user

而清单 9.14 (ii( 使用了:

get edit_user_path(@user)

有什么区别? 为了测试登录用户在未登录时会被重定向到主页,后者有效,而前者会引发错误。

从概念上讲,上面的两个语句看起来是一样的,i( 调用控制器操作,而 ii( 路由到资源

是吗?

事实上,这两个代码在概念上是等效的。

他们正在做同样的事情,通过Userscontroller中的edit操作发出GET users/edit.html.erb请求。

但是,您测试上述行为的上下文是不同的。


代码

get :edit, id: @user

是在测试控制器(UsersController(的上下文中。因此,您只需要指定操作(在本例中为"编辑"(以及必要的参数(在本例中为"id"(。

get edit_user_path(@user)

是在模拟用户浏览应用的上下文中,您可以通过集成测试执行此操作。在这里,您需要精确地了解路由路径,因为可能涉及不同的控制器。也就是说,调用操作的上下文不限于一个特定的控制器。例如,在清单 8.40 中,我们有一个模拟用户注销的集成测试:

  test "login with valid information followed by logout" do
    get login_path
    post login_path, session: { email: @user.email, password: 'password' }
    assert is_logged_in?
    assert_redirected_to @user
    follow_redirect!
    assert_template 'users/show'
    assert_select "a[href=?]", login_path, count: 0
    assert_select "a[href=?]", logout_path
    assert_select "a[href=?]", user_path(@user)
    delete logout_path
    assert_not is_logged_in?
    assert_redirected_to root_url
    # Simulate a user clicking logout in a second window.
    delete logout_path
    follow_redirect!
    assert_select "a[href=?]", login_path
    assert_select "a[href=?]", logout_path,      count: 0
    assert_select "a[href=?]", user_path(@user), count: 0
  end

在此集成测试中,涉及两个控制器:UsersControllerSessionsController

具体说来:

  • user_path(@user) assert_select "a[href=?]", user_path(@user)是关于UsersControllershow行动。
  • login_pathget login_path 中调用new操作 SessionsController .

  • login_pathpost login_path, session: { email: @user.email, password: 'password' } 中调用create操作 SessionsController .

  • login_pathassert_select "a[href=?]", login_path是关于SessionsController中的new动作。
  • assert_select "a[href=?]", logout_path logout_path是关于SessionsController destroy行动.

这在集成测试中是可能的,因为我们在调用某些操作时不限于特定的控制器。

这也解释了为什么你提供的第一个代码

get :edit, id: @user

在集成测试中引发错误。它没有指定在哪个控制器中调用edit操作。(例如,它可能是AccountActivationsControllerPasswordResetsController中的edit操作(

另外,你提出的观点

i( 调用控制器操作,而 ii( 路由到资源

很重要。

控制器测试

纯粹是通过发出相当"低级"或"机器级"的命令来测试控制器。也就是说,我们将特定的HTTP请求(在您的情况下PATCH(直接提交给控制器操作(在您的情况下edit(,而不用担心模拟用户浏览您的应用程序(即用户实际点击链接"编辑配置文件"(,您可以通过更多"高级"集成测试来完成。

最新更新