zoukankan      html  css  js  c++  java
  • Rspec: everyday-rspec实操。5:controller test(了解基础)

    5 章 控制器测试 

    5.1基础

    rails generate rspec:controller home 

    RSpec.describe HomeController, type: :controller do
      describe '#index' do
        it "responds successfully" do
          get :index
          expect(response).to be_success
          # response 对象包含应用返回给浏览器的所有数据,包括 HTTP 响应码。

          # be_success 检查响应的状态是成 功(200 响应)还是失败(例如 500 异常)。

          expect(response).to have_http_status "200" 

        end
      end
    end

    be_success匹配器 ,have_http_status()匹配器

    5.2要验证身份的controller test

    如果程序有Devise。测试的时候,需要身份验证,则使用Devise Test helpers

    Devise includes some test helpers for controller and integration tests. In order to use them, you need to include the repective module in you test cases/specs. 

    包含一个测试模块.

    class PostsControllerTest < ActionController::TestCase
    include Devise::Test::ControllerHelpers
    end
    class PostsTests < ActionDispatch::IntegrationTest
    include Devise::Test::IntegrationHelpers
    end
    RSpec.configure do |config|
    config.include Devise::Test::IntegrationHelpers, type: :feature
     config.include Devise::Test::ControllerHelpers, type: :controller
     config.include Devise::Test::ControllerHelpers, type: :view
    end

    然后就可以使用sign_in, sign_out方法了

    redirect_to 匹配器 

    以下测试都是get的测试。

    ProjectsController
      #inde
        as an authenticated user
          responds successfully
          returns a 200 response
        as a guest
          returns a 302 response
          redirects to the sign_in page
      #show
        as an authorized user
          responds successfully
        as an unauthorized user
          redirects to the dashboard

    5.3 测试用户输入。

    HTTP GET外,还有POST, PATCH, DELETE与controller交互。

    Method: FactoryBot::Syntax::Methods#attributes_for

    #attributes_for(name, *traits_and_overrides, &block) ⇒ Hash

    根据factories中的注册的name, 生成一个hash属性。

      describe '#create' do
        context "as an authenticated user" do
          before do
            @user = FactoryGirl.create(:user)
          end
          it "adds a project" do
            project_params = FactoryGirl.attributes_for(:project)
            sign_in @user
            expect {
              post :create, params: {project: project_params }
            }.to change(@user.projects, :count).by(1)

    #expect(@user.projects.count).to eq(1)  #替代方法 

          end
        end


    change()方法,by()方法,是哪里定义的? 

    在gem rspec-expectations 中定义的。

    This class is part of a private API. 文档提示:私有类,尽量避免使用.

    https://www.rubydoc.info/gems/rspec-expectations/RSpec/Matchers:change 

      describe '#update' do
        context 'as an authorized user' do
          before do
            @user = FactoryGirl.create(:user)
            @project = FactoryGirl.create(:project, owner: @user)
          end
          it "updates a project" do
            project_params = FactoryGirl.attributes_for(:project, name: "New Project Name")
            sign_in @user
            patch :update, params: {id: @project.id, project: project_params}

    #已经更新数据库,但内存里@project实例变量没有更新,所以要reload. 

            @project.reload
            expect(@project.name).to eq "New Project Name"
          end
        end
      end

    reload()方法 从数据库中根据接收者的primary-key id调取record并更新接收者的属性。

    Reloading is commonly used in test suites to test something is actually written to the database, or when some action modifies the corresponding row in the database but not the object in memory:

    经常用于测试,测试记录实际已写入数据库,或者测试当一些action在数据库中修改了相关记录但在内存中已存在这个对象变量是否更新。

    5.4 测试用户输入导致的错误 


        context "with invalid attributes" do
          before do
            @user = FactoryGirl.create(:user)
          end
          it "does not add a project" do
            project_params = FactoryGirl.attributes_for(:project, :invalid)
            sign_in @user
            post :create, params: {project: project_params}
            expect(@user.projects.count).to eq(0)
            # expect {
            #   post :create, params: { project: project_params }
            # }.to_not change(@user.projects, :count)
          end
        end

    这里用到trait,在projects.rb的中定义的一个trait

    trait :invalid do

      name nil

    end 

    ⚠️ trait 和 factory继承的区别,一个是增加特点,用的时候需要和预构件一起用;一个是完全继承父类属性并增加自己的特色,是一个新的预构件。

    5.5

    处理非 HTML 输出 ,如何编写对JSON格式的测试。

    bin/rails g rspec:controller tasks 

    spec/controllers/tasks_controller_spec.rb 测试控制器show动作
    RSpec.describe TasksController, type: :controller do
      before do
        @user = FactoryGirl.create(:user)
        @project = FactoryGirl.create(:project, owner:@user)
        @task = @project.tasks.create!(name: "Test task")
      end
      describe '#show' do
        it "responds with JSON formatted output" do
          sign_in @user
          get :show, format: :json,
            params:{project_id: @project.id, id: @task.id}
          expect(response.content_type).to eq "application/json"
        end
      end
    end
    通过format: :json格式,控制器处理相应的请求,返回application/json类型的内容。

    content_type方法属于 ActionDispatch::Response类的实例方法。

    5.6小结

    控制器测试,测试的是user登陆和未登陆状态下,已经不同用户权限下,对action 是否成功的测试。

    在实际测试中,控制器测试已经不流行了。 

  • 相关阅读:
    Java-01,计算1-10的阶乘之和
    软件工程研究生面试机试考题-2018
    nginx会话保持之sticky模块
    Dubbo原理简介、与Zookeeper整合利用
    Day41 openstack基础
    krb5-libs这个RPM包删掉了导致ssh无法连接
    day40 数据结构-算法(二)
    进程上下文频繁切换导致load average过高
    day39 算法基础
    应用性能管理工具PinPoint介绍
  • 原文地址:https://www.cnblogs.com/chentianwei/p/9055336.html
Copyright © 2011-2022 走看看