Rails 5 с Devise, тестирование контроллеров с Rspec (действие по уничтожению) - PullRequest
1 голос
/ 29 сентября 2019

Я реализую тест rspec для действия destroy, концепция заключается в том, что вошедший в систему пользователь может уничтожать только свои собственные сообщения и не может уничтожать сообщения, созданные другими пользователями.

The `new_post` is created by a user named `creator`, and another user named `user1` signed in and try to delete the `new_post`, it should not be able to delete it, because of the `  before_action :authenticate_user!, only: %i[create destroy]` in Posts controller

Контроллер сообщений.

class PostsController < ApplicationController
  before_action :set_post, only: %i[show edit update destroy]
  before_action :current_user, only: %i[create destroy]
  before_action :authenticate_user!, only: %i[create destroy]
  .
  .
  .

  def destroy
    @post.destroy
    respond_to do |format|
      format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private

  def set_post
    @post = Post.find(params[:id])
  end


  def post_params
    params.require(:post).permit(:content, :picture)
  end
end

спецификация контроллера пользователя

require 'rails_helper'
RSpec.describe PostsController, type: :controller do
  context  'DELETE #destroy' do

    let(:user1) {User.create!(name:"John", email:"john@mail.com", password:"password")}

    let(:creator) { User.create!(name: "creator", email: "creaor@gmail.com", password: "password") }

    let(:new_post){creator.posts.create!(content: "Neque porro quisquam est qui dolorem ipsum")}


    it 'A user cannot delete a post created by other user' do
      sign_in user1
      p (new_post)
      expect { delete :destroy, params: { id: new_post.id } }.to change(Post, :count).by(0)

    end
  end
end

Сбои:

  1) PostsController DELETE #destroy A user cannot delete a post created by other user
     Failure/Error: expect { delete :destroy, params: { id: new_post.id } }.to change(Post, :count).by(0)
       expected `Post.count` to have changed by 0, but was changed by -1

Ответы [ 2 ]

2 голосов
/ 30 сентября 2019

Я считаю, что вам нужно добавить проверку проверки к вашему коду. authenticate_user! аутентифицирует , что лицо, делающее запрос, вошло в систему. Однако оно не проверяет, авторизован ли пользователь , авторизован ли для выполнения запроса, который он делает.

См. Аутентификация против авторизации , чтобы немного подробнее обсудить две концепции. И посмотрите на https://stackoverflow.com/a/25654844/868533 для хорошего обзора популярных жетонов авторизации в Rails. Чтобы было ясно, вы почти наверняка захотите способ аутентификации пользователей (Devise) вместе с гемом авторизации.

Предполагая, что вы решите использовать CanCanCan (это распространенный вариант, который я использовалв прошлом) вы добавили бы класс Ability, например:

class Ability
  include CanCan::Ability

  def initialize(user)
    if user.present?
      can :destroy, Post, user_id: user.id
    end
  end
end

Затем вы можете добавить before_action :check_authorization, only: %i[destroy] как новый before_action на свой контроллер, и ваши тесты должны пройти без каких-либо изменений.

1 голос
/ 30 сентября 2019

Помните. Вы пишете тест контроллера. Итак, этот тест unit test. Существует два основных способа авторизации в Devise. Они авторизуют маршруты и авторизируют контроллер. Если вы используете авторизационные маршруты, когда вы пишете rspec для контроллера, вы должны использовать stub для подделки авторизованного доступа.

...