DEV Community

Alexandre
Alexandre

Posted on

Testando Request em RSpec Rails

Anteriormente, nós fizemos teste para model, agora vamos fazer teste para requests.

O que é o request e porque é importante testar ele.

Antes de nós testar, primeiramente, nós temos que entender o request, que traduzindo seria, requisição.

Você deve saber, eu espero, que a nossa internet funciona com base de requisição e resposta, ou seja, no meu navegador, eu estou requisitando uma página web para um servidor, e o servidor, por sua vez, vai me dar uma resposta sobre a requisição.

O servidor pode aceitar a requisição, pode negar ou até mesmo pode dar erro.

E é esse o nosso objetivo, nós queremos testar o que acontece quando faço requisição de formato HTML ou JSON, ou então quando acesso em uma página não autorizada, etc.

Então, para começar, vamos criar uma aplicação do começo para que vocês consigam me acompanhar.

A nossa ideia da aplicação é um simples blog, onde vai ter um controller e um model que é o post.

Se você quiser me acompanhar, basta executar os comandos abaixo para criar a aplicação.

rails new blog --skip-test
cd blog
echo 'gem "rspec-rails", group: [:development, :test]' >> Gemfile
echo 'gem "rails-controller-testing", group: :test' >> Gemfile
bundle install
rails g rspec:install
rails g resource Post titulo corpo:text
rails db:create db:migrate
Enter fullscreen mode Exit fullscreen mode

Pronto com isso, estamos pronto para testar.

Testando

Beleza, para testar os requests não é tão difícil assim.

vamos escrever os testes

# spec/requests/posts_spec.rb
require 'rails_helper'

RSpec.describe "Posts", type: :request do
  describe "GET posts" do
    it "deve retornar sucesso" do
      get posts_path

      expect(response).to have_http_status(:success)
    end
  end

  describe "GET post" do
    it "deve retornar sucesso" do
      post = Post.create(titulo: "Ólá", corpo: "bla bla bala")
      get post_path(post)

      expect(response).to have_http_status(:success)
    end

    it "deve ser redirecionado por não existir o post" do
      get post_path("não existo")

      expect(response).to have_http_status(:not_found)
    end
  end

  describe "GET new post" do
    it "deve retornar sucesso" do
      get new_post_path

      expect(response).to have_http_status(:success)
    end
  end

  describe "Post posts" do
    it "deve retornar created" do
      post posts_path, params: {
        post: {
          titulo: "Reza a lenda",
          corpo: "Ele está vindo"
        }
      }

      expect(response).to redirect_to(post_path(assigns(:post)))
    end
  end

  describe "GET edit post" do
    it "deve retornar sucesso" do
      post = Post.create(titulo: "Ólá", corpo: "bla bla bala")
      get edit_post_path(post)

      expect(response).to have_http_status(:success)
    end

    it "deve ser redirecionado por não existir o post" do
      get edit_post_path("não existo")

      expect(response).to have_http_status(:not_found)
    end
  end

  describe "PUT post" do
    it "deve retornar sucesso" do
      post = Post.create(titulo: "Ólá", corpo: "bla bla bala")
      put post_path(post), params: {
        post: {
          titulo: "sou eu o",
          corpo: "tiririca"
        }
      }

      expect(response).to redirect_to(post_path(assigns(:post)))
    end

    it "deve ser redirecionado por não existir o post" do
      put post_path("não existo"), params: {
        post: {
          titulo: "sou eu o",
          corpo: "tiririca"
        }
      }

      expect(response).to have_http_status(:not_found)
    end
  end

  describe "DELETE post" do
    it "deve retornar sucesso" do
      post = Post.create(titulo: "Ólá", corpo: "bla bla bala")
      delete post_path(post)

      expect(response).to have_http_status(:redirect)
    end

    it "deve ser redirecionado por não existir o post" do
      delete post_path("não existo")

      expect(response).to have_http_status(:not_found)
    end
  end
end

Enter fullscreen mode Exit fullscreen mode

É meio grandinho, mas não tem muitas diferenças em teste de model, como nós fizemos antes.

Só vamos dar a atenção nesses métodos que vou citar.

  • get
  • post
  • put
  • delete
  • have_http_status
  • redirect_to
  • assigns

É só isso, porém existe mais métodos, como patch etc, mas raramente você usa ele.

Os primeiros quatros métodos são, obviamente, métodos de requisição HTTP, se não sabe sobre isso, eu recomendo que estude isso, porque isso é bastante importante.

Não tem muito o que explicar sobre eles, pois o próprio nome diz o que eles fazem.

Então vamos para have_http_status e redirect_to.

O have_http_status é um método para verificar se o argumento passado é equivalente ao "status code" da resposta do servidor.

Enquanto o redirect_to é o método para verificar se o argumento passado é equivalente ao página que o servidor redirecionou.

Não tem muito segredo, se você entende de protocolo HTTP.

Agora nós temos o método assigns, ele relaciona com a variável da instância, ou seja, vamos pegar o nosso caso, o argumento que eu passei foi :post, isso seria o equivalente o @post, isso é útil para caso em que você quer o id do post, que é o nosso caso, ou então saber que ele foi criado ou atualizado com sucesso.

Pronto, terminei com a explicação, agora vamos testar.

rspec

Finished in 0.4995 seconds (files took 4.57 seconds to load)
13 examples, 11 failures, 2 pending

Failed examples:

rspec ./spec/requests/posts_spec.rb:5 # Posts GET posts deve retornar sucesso
rspec ./spec/requests/posts_spec.rb:13 # Posts GET post deve retornar sucesso
rspec ./spec/requests/posts_spec.rb:20 # Posts GET post deve ser redirecionado por não existir o post
rspec ./spec/requests/posts_spec.rb:28 # Posts GET new post deve retornar sucesso
rspec ./spec/requests/posts_spec.rb:36 # Posts Post posts deve retornar created
rspec ./spec/requests/posts_spec.rb:49 # Posts GET edit post deve retornar sucesso
rspec ./spec/requests/posts_spec.rb:56 # Posts GET edit post deve ser redirecionado por não existir o post
rspec ./spec/requests/posts_spec.rb:64 # Posts PUT post deve retornar sucesso
rspec ./spec/requests/posts_spec.rb:76 # Posts PUT post deve ser redirecionado por não existir o post
rspec ./spec/requests/posts_spec.rb:89 # Posts DELETE post deve retornar sucesso
rspec ./spec/requests/posts_spec.rb:96 # Posts DELETE post deve ser redirecionado por não existir o post
Enter fullscreen mode Exit fullscreen mode

Bem, nós esquecemos de criar as actions do controller e as views.

Vamos para app/controller/posts_controller.rb e criar as actions.

# app/controller/posts_controller.rb

class PostsController < ApplicationController
    before_action :define_post, except: [:index, :new, :create]

    def index
          @post = Post.all
    end

    def show
    end

    def new
    end

    def create
        @post = Post.new 

        if @post.save
            redirect_to post_path(@post)
        else
            render :new, status: :unprocessable_entity
        end
    end

    def edit
    end

    def update
        if @post.update post_params
            redirect_to post_path(@post)
        else
            render :edit
        end
    end

    def destroy
        if @post.destroy
            redirect_to posts_path
        end
    end

    private

    def post_params
        params.require(:post).permit(:titulo, :corpo)
    end

    def define_post
        begin
            @post = Post.find(params[:id])
        rescue ActiveRecord::RecordNotFound
            redirect_to posts_path, status: :not_found
        end
    end
end
Enter fullscreen mode Exit fullscreen mode

Pronto, criamos as actions, agora vamos criar as views, basta executar os comandos abaixo.

touch app/views/posts/index.html.erb app/views/posts/show.html.erb app/views/posts/new.html.erb app/views/posts/edit.html.erb
Enter fullscreen mode Exit fullscreen mode

Agora sim, nós estamos pronto, vamos rodar o teste.

rspec

Finished in 0.81536 seconds (files took 4.77 seconds to load)
13 examples, 0 failures, 2 pending
Enter fullscreen mode Exit fullscreen mode

Passou.

E é isso, terminamos aqui, só que não, eu estava pensando aqui, será que vale a pena fazer um teste para uma aplicação de API? Pois é útil aprender como que testa as requisições do tipo JSON.

Mas não vale a pena, porque seria um copiar e colar e colocar um argumento header e testar se resposta é json.

Eu só vou fazer só um teste de requisição para ter noção.

Vamos para spec/requests/post_spec.rb.

# spec/requests/post_spec.rb
require 'rails_helper'

RSpec.describe "Posts", type: :request do
  describe "GET posts" do
    ...

    describe "requisição json" do
      it "deve retornar sucesso" do
        headers = { "ACCEPT": "application/json" }
        get posts_path, headers: headers

        expect(response.content_type).to eq("application/json; charset=utf-8")
        expect(response).to have_http_status(:success)
      end
    end
  end
  ...
end
Enter fullscreen mode Exit fullscreen mode

Se nós analisamos o teste, vai perceber que não teve muita diferença o que a gente fez anteriormente, eu passei o argumento headers no get e testei se o tipo de conteúdo é JSON, só isso.

Se nós rodar o teste, é obvio que vai falhar, então para evitar isso, vamos para app/controller/post_controller.rb.

class PostsController < ApplicationController
  ...
  def index
    @posts = Post.all

    respond_to do |format|
      format.html
      format.json { render json: @posts }
    end
  end
  ...
end
Enter fullscreen mode Exit fullscreen mode

Com isso, a nossa aplicação aceita a requisição HTML e JSON.

Agora, se nós rodar o teste, vai funcionar, e isso é o suficiente para nós testar a aplicação que atende requisição json.

Com isso, nós terminamos aqui.

Tchau!

Top comments (0)