Rails Rails 中对 Controllers 的测试如何断言 controller 内部状态?

alpha0x00 · 2023年11月12日 · 最后由 alpha0x00 回复于 2023年11月12日 · 428 次阅读

初学 Rails,关于测试代码我有如下了解: Rails 中大概分为了对 model、controllers、integration 和 system 的测试。

ModelTest 直接继承 ActiveSupport::TestCase,model 的测试不涉及 server,只是利用 orm 框架对 model 的完整性和正确性做测试; 在 Rails5 之前,ControllerTest 继承的是 ActionContollersTest,而目前 ControllerTest 和 IntegrationTest 都是继承 ActionDispatch::IntegrationTest, 所以 controllers 是对 server 接口的测试,是从 server 系统 外部 来看待并测试 server,算是黑盒测试,不能审视 server 内部状体比如 session 的变化; integration 是对用户使用的重要流程,或者涉及接口的依赖的测试,也是黑盒测试; system 测试是完全模拟用户打开浏览器看到的样子,来进行测试,也是黑盒测试

从上面来看,我的最大疑问是,Controller 和 Integration 都是黑盒测试,没办法观察系统内部状态并断言,Rails 中是不是有相关机制能办到呢?或者说 Rails 中不建议这样做,那么理由又是啥呢?

ref: rails5 can't access session in ActionDispatch::IntegrationTest https://github.com/rails/rails/issues/23386

你说的 controller 内部状态包括 其内部实例变量,使用这个 rails 的这个 gem 能解决: https://github.com/rails/rails-controller-testing

class PostControllerTest < ActionController::TestCase
  def test_index
    get :index
    assert_equal Post.all, assigns(:posts)
  end

而 session 的测试,如当前登录用户,在 test/test_helper.rb 中写一个方法 , 然后在 controller testcase 中就可以直接使用了。例如我的代码:

# test/test_helper.rb
class ActiveSupport::TestCase
  def current_user
    if session[:current_active_session_id].present?
      ActiveSession.find_by(id: session[:current_active_session_id])&.user
    else
      cookies[:remember_token].present?
      ActiveSession.find_by(remember_token: cookies[:remember_token])&.user
    end
  end

cookie 的测试:

test "should remember user when logging in" do
  assert_nil cookies[:remember_token]

  post login_path, params: {
    user: {
      email: @confirmed_user.email,
      password: @confirmed_user.password,
      remember_me: 1
    }
  }

  assert_not_nil current_user
  assert_not_nil cookies[:remember_token]
end
qichunren 回复

感谢回答。我按照你的提示验证了下,确实 IntegrationTest 类中可以访问 session、flash 和 cookie,那么这样看看来 ControllerTest 就不算是黑盒测试嘛。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号