ruby 使用rspec测试请求

uurity8g  于 2023-04-20  发布在  Ruby
关注(0)|答案(1)|浏览(125)
  • 嘿,伙计们,我试图建立测试我的控制器使用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
plicqrtu

plicqrtu1#

你还没有真正理解工厂是什么以及如何使用它们,工厂应该生成你可以在测试中使用的唯一数据。
因此,为了清理你的工厂,你可以使用ffaker gem来生成伪随机数据,而不是你自己的个人数据(你不应该这样使用):

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

在测试中使用伪随机数据可以避免你的测试依赖于测试之外的信息,这也是你使用工厂而不是fixture的最大原因之一。
然后,在测试设置阶段使用规范中的工厂:

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

相关问题