在 Gemfile 裡面加入兩個 gem,是寫測試很常用到的工具

  • factory_bot_rails 以前叫 factory_girl_rails 不過後來更名了,是很好用的產生測試資料工具。
  • faker 是很好用的產生假資料工具
group :development, :test do
  # ...

  gem "factory_bot_rails"
  gem "faker"

  # ...
end

設定 factory bot

編輯 spec/rails_helper.rb 加入 syntax method

RSpec.configure do |config|
  # ...
  config.include FactoryBot::Syntax::Methods
  # ...
end

建立產生測試資料的檔案

touch spec/factories.rb

FactoryBot.define do
  factory :api_access_token do
    association :user, factory: [:user]
    key { SecureRandom.uuid.delete("-") }
  end

  factory :user do
    email { Faker::Internet.email }
    password { "a00000000" }
    password_confirmation { "a00000000" }
  end

  factory :post do
    title { Faker::Lorem.question }
    context { Faker::Lorem.paragraph_by_chars }
  end
end

測試 app/api/api_v0/posts.rb 的 CRUD 行為(這裡先只測成功案例,可以在自行挑戰補上失敗案例)

建立檔案

touch spec/api/api_v0/posts_spec.rb

以下是完整的 CRUD 測試

describe ApiV0::Posts do
  before(:all) do
    @user = create(:user)
    @posts = create_list(:post, 3, user: @user)
    @access_token = create(:api_access_token, user: @user)
  end

  context 'GET /api/v0/posts' do
    it 'should return 200 and posts' do
      get '/api/v0/posts', params: { access_key: @access_token.key }

      result = JSON.parse(response.body)

      expect(response.status).to eq(200)
      expect(result.size).to eq(@user.posts.size)
    end
  end

  context "Get /api/v0/posts/:id" do
    it "return a post by id" do
      post = create(:post, user: @user)

      get "/api/v0/posts/#{post.id}", params: { access_key: @access_token.key }

      result = JSON.parse(response.body)

      expect(response.status).to eq(200)
      expect(result["title"]).to eq(post.title)
    end
  end

  context "Post /api/v0/posts" do
    it "create new post" do

      title = "Title"
      context = "Context"

      post "/api/v0/posts", params: { access_key: @access_token.key, title: title, context: context }

      result = JSON.parse(response.body)

      expect(response.status).to eq(201)
      expect(result["title"]).to eq(title)
      expect(result["context"]).to eq(context)
    end
  end

  context "Pacth /api/v0/posts/:id" do
    it "update a post by id" do
      post = @user.posts.last

      title = "Edited title"
      context = "Edited context"

      patch "/api/v0/posts/#{post.id}", params: { access_key: @access_token.key, title: title, context: context }

      result = JSON.parse(response.body)

      expect(response.status).to eq(200)
      expect(result["title"]).to eq(title)
      expect(result["context"]).to eq(context)
    end
  end

  context "Delete /api/v0/posts/:id" do
    it "delete a post by id" do
      post = @user.posts.last

      delete "/api/v0/posts/#{post.id}", params: { access_key: @access_token.key }

      result = JSON.parse(response.body)

      expect(response.status).to eq(200)
      expect(result["title"]).to eq(post.title)
      expect(result["context"]).to eq(post.context)
      expect{ Post.find(post.id) }.to raise_error ActiveRecord::RecordNotFound
    end
  end
end

跑跑看結果是不是 all pass?

ApiV0::Ping
  GET /api/v0/ping
    should return 200 and pong

ApiV0::Posts
  GET /api/v0/posts
    should return 200 and posts
  Get /api/v0/posts/:id
    return a post by id
  Post /api/v0/posts
    create new post
  Pacth /api/v0/posts/:id
    update a post by id
  Delete /api/v0/posts/:id
    delete a post by id

Finished in 0.34945 seconds (files took 1.38 seconds to load)
6 examples, 0 failures
Copyright © NicLin 2019 all right reserved,powered by Gitbook該頁面生成時間: 2019-04-09 10:00:37

results matching ""

    No results matching ""