Тестирование запросов с помощью rspec

  • Привет, ребята, я пытаюсь создать тесты для своих контроллеров с помощью rspec, у меня есть 3 модели и контроллеры, т.е. пользовательский, платежный и домашний -Эти режимы связаны в поиске таким образом, что платеж принадлежит пользователю и дому, дом имеет много платежей, а пользователь имеет много платежей.

-Мне удалось написать тесты для этих ассоциаций для моделей, теперь застрял на контроллерах.

  • Ниже то, что я пытался написать
require 'rails_helper'

RSpec.describe 'Payments', type: :request do
  let(:valid_attributes) do
    { first_name: 'mutebi', last_name: 'godfrey', phone_number: '+256780140670', address: 'kampala', money_paid: '6000', date: '25/08/2023',
      nin_number: 'KK45896587450P', user_id: '5', home_id: '9' }
  end

  let(:invalid_attributes) do
    skip('Add a hash of attributes invalid for your model')
  end

  describe 'GET /index' do
    it 'renders a successful response' do
      Payment.create! valid_attributes
      get payments_url, headers: valid_headers, as: :json
      expect(response).to be_successful
    end
  end

  describe 'GET /show' do
    it 'renders a successful response' do
      payment = Payment.create! valid_attributes
      get payment_url(payment), as: :json
      expect(response).to be_successful
    end
  end
end
  • и получить эту ошибку ниже в консоли. я думаю проблема может быть в ассоциациях
  1) Payments GET /index renders a successful response
     Failure/Error: Payment.create! valid_attributes
     
     ActiveRecord::RecordInvalid:
       Validation failed: User must exist, Home must exist
     # ./spec/requests/payments_spec.rb:17:in `block (3 levels) in <main>'

  2) Payments GET /show renders a successful response
     Failure/Error: payment = Payment.create! valid_attributes
     
     ActiveRecord::RecordInvalid:
       Validation failed: User must exist, Home must exist
     # ./spec/requests/payments_spec.rb:25:in `block (3 levels) in <main>'
  • Ниже мой контроллер, который я пытаюсь проверить
# frozen_string_literal: true

module Api
  module V1
    class PaymentsController < ApplicationController
      before_action :authenticate_user!
      before_action :set_payment, only: %i[show edit update destroy]
      # GET /payments or /payments.json
      def index
        if user_signed_in?
          @payments = current_user.payments.order(created_at: :desc)
          render json: @payments.to_json(include: %i[home user])
        else
          render json: {}, status: 401
        end
      end

      # GET /payments/1 or /payments/1.json
      def show
        @payment = current_user.payments.find(params[:id])
        render json: @payment.to_json(include: %i[home user])
      end

      # GET /payments/new
      def new
        @home = Home.find(params[:home_id])
        @payment = @home.payments.new
      end

      # GET /payments/1/edit
      def edit; end

      # POST /payments
      def create
        @home = Home.find(params[:home_id])
        @payment = @home.payments.create(payment_params) do |p|
          p.user = current_user # if user_signed_in?
        end
        if @payment.save
          render json: @payment.to_json(include: %i[home user])
        else
          render json: @payment.errors, status: :unprocessable_entity
        end
      end

      # PATCH/PUT /payments/1 or /payments/1.json
      def update
        @home = Home.find(params[:home_id])
        @payment = @home.payments.find(params[:id])
        if @payment.update
          render json: { notice: 'Payment was successfully updated.' },
                 status: :ok
        else
          render json: { error: 'Unable to update payment' },
                 status: :unprocessable_entity
        end
      end

      # DELETE /payments/1 or /payments/1.json

      def destroy
        @home = Home.find(params[:home_id])
        @payment = @home.payments.find(params[:id])
        @payment.destroy
        render json: { notice: 'Payment succefully removed' }
      end

      private

      # Use callbacks to share common setup or constraints between actions
      def set_payment
        @payment = Payment.find(params[:id])
      end

      # Only allow a list of trusted parameters through.
      def payment_params
        params.require(:payment).permit(:first_name, :last_name, :phone_number, :address, :money_paid, :date,
                                        :nin_number, :user_id, :home_id)
      end
    end
  end
end

Вы пометили вопрос с помощью FactoryBot, но на самом деле вы его не используете. Я думаю, что довольно ясно, где вам нужно провести больше исследований. Кроме того, то, как вы структурируете эти тесты, довольно странное - Payment.create! valid_attributes не относится к примеру. Настройка зависимостей теста должна выполняться через let! или before, чтобы вам не пришлось повторяться.

max 13.04.2023 14:00

Я хотел бы знать, как я могу использовать заводские рельсы для ботов. Я использовал его со спецификациями модели, что легко, но с запросами мне оказалось сложно реализовать

mutebi ug official 13.04.2023 18:33

Ну, что вы на самом деле пробовали/исследовали? В чем проблема, которую вы обозначили? Для этой комбинации нет недостатка в обучающих программах.

max 13.04.2023 18:46

я использовал factory_bot_rails с моделями, как показано ниже. FactoryBot.define do factory :payment do first_name { 'Mutebi' } last_name { 'Godfrey' } phone_number { '+256780140670' } address { 'Kampala' } money_paid { '9.99' } nin_number { 'NLJ8589654785P' } home_id { 1 } date { '2023-04-07' } user_id { '7' } статус { 'ожидание' } домашний пользователь end end . я только застрял в том, как я могу использовать эту спецификацию запроса

mutebi ug official 13.04.2023 19:22

Вы бы использовали фабрики, например, с let!(:payments) { FactoryBot.create_list(:payments, 3) }. Но вы не должны жестко кодировать эти идентификаторы - НИКОГДА. Вместо этого следуйте инструкциям по ассоциациям github.com/thoughtbot/factory_bot/blob/main/…

max 13.04.2023 20:04

Макс дал много полезных советов, но чтобы ответить на ваш вопрос прямо: да, вы можете использовать FactoryBot для всех тестов, моделей, контроллеров и т. д. Ошибка, которую вы получаете, связана с тем, что рельсы ожидают, что будет пользователь с идентификатором 5 и Дома с идентификатором 9, но вы их не создали.

Mike Szyndel 13.04.2023 21:13

Короткий и милый FactoryBot можно использовать для любого теста, контроллера и модели.

Rutik Patel 15.04.2023 16:43
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
99
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы так и не поняли, что такое фабрики и как их использовать. Фабрики должны генерировать уникальные данные, которые вы сможете использовать в своих тестах.

Таким образом, чтобы очистить свою фабрику, вы можете использовать гем ffaker для генерации псевдослучайных данных вместо ваших личных данных (которые вы не должны использовать следующим образом):

FactoryBot.define do 
  factory :payment do 
    first_name { FFaker::Name.first_name } 
    last_name { FFaker::Name.last_name } 
    phone_number { FFaker::PhoneNumberNL.international_mobile_phone_number } 
    address { FFaker::Address.street_address } 
    money_paid { FFaker::Number.decimal } 
    nin_number { FFaker::Identification.ssn } 
    user # DO NOT HARDCODE ID's!
    home # DO NOT HARDCODE ID's!
  end
end

Использование псевдослучайных данных в ваших тестах позволяет избежать того, чтобы ваши тесты зависели от информации, не относящейся к тесту. Это одна из главных причин, почему вы должны использовать фабрики вместо приспособлений.

Затем вы используете фабрику в своих спецификациях на этапе настройки теста:

require 'rails_helper'

RSpec.describe 'Payments', type: :request do
  let(:payment) { FactoryBot.create(:payment) }

  describe 'GET /index' do
    let!(:payments) { FactoryBot.create_list(:payment, 5) }
    it 'renders a successful response' do
      get payments_url, headers: valid_headers, as: :json
      expect(response).to be_successful
    end
  end

  describe 'GET /show' do
    it 'renders a successful response' do
      get payment_url(payment), as: :json
      expect(response).to be_successful
    end

    it 'has the correct JSON' do
      get payment_url(payment), as: :json
      expect(response.parsed_body).to match(a_hash_including(
        payment.attributes.slice(
          "first_name", "last_name", "address" # ...
        )
      ))
    end
  end
end

Спасибо за твои усилия, брат. ты дал мне шаг, чтобы пойти

mutebi ug official 16.04.2023 00:29

Другие вопросы по теме