Rails 测试 Controller Action 的方式

之前写 Rails 测试都是从 models 来写的,原因很简单,controller 的逻辑一般比较简单,不会太容易出错,而 model 里的逻辑比较复杂,稍不留神就会出现问题,只能多测。

但是这种思想就导致了 controller 甚至都不想跑,写完了就直接运行。随着项目的进度不断前进,controller 里的 action 越来越多,同时一次写对的概率也变少了很多,特别是在跟前端对接的时候,状况不断。

本着 吃自己的狗食 的精神,我也开始慢慢的写了一些 controller 的测试

网上关于 controller 的测试大多数都是基于 RSepc 的,由于我不太喜欢这个东西,所以自己使用的是官方默认的 MiniTest, 看了一下官方的源码 大概是这么个样子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
require 'test_helper'

class FlowTemplatesControllerTest < ActionController::TestCase

  test "could list all flow templates" do
    get :index
    assert_response :success
    response = get :index, language: "ruby"
    json = JSON.parse(response.body)
    assert_response :success
    assert_equal FlowTemplate.where(language: "ruby").count, json.count
  end

  test "could show flow template" do
    flow_template = FlowTemplate.first
    response = get :show, id: flow_template.id.to_s
    json = JSON.parse(response.body)
    assert_equal flow_template.name, json["name"]
  end
end

能说的可能就是 这个地方可以支持 get post patch delete 了,之后这里会默认找这个 test 命名中对应的 controller。

上面的是最普通的情况,在实际的测试当中,有时候我们还会遇到诸如 这个地方需要登录的情况,但是我在 controller 里手动的去登录非常麻烦(这也是我不想写 controller 的测试的主要原因),其实可以用 instance_eval 来解决这个问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
require 'test_helper'

class ProjectsControllerTest < ActionController::TestCase
  setup do
    user = User.first || Fabricate(:user)
    @controller.instance_eval do
      @current_user = user
    end
    @user = user
  end

  test "could list all projects" do
    Fabricate(:project, user: @user)
    assert_equal User.first.id.to_s, Project.first.user.id.to_s
    get :index
    assert_response :success
  end

  test "could create project" do
    assert_equal 0, Project.count
    post :create, { name: "jicheng1014/test", source: "github", git_url: "git@github.com:jicheng1014/test.git" }
    assert_response :success
    assert_equal 1, Project.count
  end
end

大概就是上面这样, have fun

Comments