title: Rails 6 API Rspec request test - Conflicting behavior
body: <p>I need help with my current testing approach.  I am currently testing my React-Rails app using Rspec and initially I setup this in my favourite_cocktail controller: </p>
  
  <pre><code>  def destroy
        @favouritecocktail = FavouriteCocktail.find(params[:id])
        @favouritecocktail.delete
    end
  </code></pre>
  
  <p>On testing the DELETE request using the code below:</p>
  
  <pre><code> describe 'DELETE /api/v1/favourite_cocktails/:id' do
      let!(:users) { FactoryBot.create(:user) }
      let!(:cocktails) { FactoryBot.create(:cocktail) }
      let!(:favourite_cocktail) { FactoryBot.create_list(:favourite_cocktail, 10, cocktail: cocktails) }
      let(:cocktail_id) { favourite_cocktail.first.id }
  
  
      before do
        sign_in users
      end
  
      before { delete "/api/v1/favourite_cocktails/#{cocktail_id}" }
  
  
      it 'returns status code 204' do
        expect(response).to have_http_status(204)
      end
    end
  </code></pre>
  
  <p>it passes, but on my app, the function responsible for deleting the user's favourite cocktail does not work. That is when I click a button to remove a users' favourite cocktail it does not work. </p>
  
  <p>However, if I refactor the <strong>destroy</strong> action method in the favourite_cocktail controller to this:</p>
  
  <pre><code>   def destroy
        @favouritecocktail = current_user.favourite_cocktails.find_by(cocktail_id: params[:id])
        @favouritecocktail.delete
     end
  </code></pre>
  
  <p>the function responsible for deleting the user's favourite cocktail works on the application. But when I run the test again: </p>
  
  <pre><code> describe 'DELETE /api/v1/favourite_cocktails/:id' do
      let!(:users) { FactoryBot.create(:user) }
      let!(:cocktails) { FactoryBot.create(:cocktail) }
      let!(:favourite_cocktail) { FactoryBot.create_list(:favourite_cocktail, 10, cocktail: cocktails) }
      let(:cocktail_id) { favourite_cocktail.first.id }
  
  
      before do
        sign_in users
      end
  
      before { delete "/api/v1/favourite_cocktails/#{cocktail_id}" }
  
  
      it 'returns status code 204' do
        expect(response).to have_http_status(204)
      end
    end
  </code></pre>
  
  <p>it fails and this is the error message I get during the RSpec testing:</p>
  
  <pre><code>Api::V1::FavouriteCocktailsController DELETE /api/v1/favourite_cocktails/:id returns status code 204
       Failure/Error: @favouritecocktail.delete
  
       NoMethodError:
         undefined method `delete' for nil:NilClass
       # ./app/controllers/api/v1/favourite_cocktails_controller.rb:47:in `destroy'
       # ./spec/requests/favourite_cocktails_spec.rb:80:in `block (3 levels) in &lt;main&gt;'
       # ./spec/rails_helper.rb:112:in `block (3 levels) in &lt;top (required)&gt;'
       # ./spec/rails_helper.rb:111:in `block (2 levels) in &lt;top (required)&gt;'
  
  </code></pre>
  
  <p>Now the preferred approach I want is such that my remove favourite_cocktail should work on the application and the Rspec test should hit the DELETE route such that it passes.  I know that there is no record of favourite_cocktails created when using FactoryBot and my concern is how to make FactoryBot create a record to be deleted.  Below are codes for the API:</p>
  
  <p><strong>Gemfile</strong></p>
  
  <pre><code>ruby '2.6.1'
  
  # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
  gem 'rails', '~&gt; 6.0.2', '&gt;= 6.0.2.2'
  # Use postgresql as the database for Active Record
  gem 'pg', '&gt;= 0.18', '&lt; 2.0'
  # Use Puma as the app server
  gem 'puma', '~&gt; 4.1'
  # Use SCSS for stylesheets
  gem 'sass-rails', '&gt;= 6'
  # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
  gem 'webpacker', '~&gt; 4.0'
  # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
  gem 'turbolinks', '~&gt; 5'
  # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
  gem 'jbuilder', '~&gt; 2.7'
  # Use Redis adapter to run Action Cable in production
  # gem 'redis', '~&gt; 4.0'
  # Use Active Model has_secure_password
  # gem 'bcrypt', '~&gt; 3.1.7'
  
  # Use Active Storage variant
  # gem 'image_processing', '~&gt; 1.2'
  
  # Reduces boot times through caching; required in config/boot.rb
  gem 'bootsnap', '&gt;= 1.4.2', require: false
  gem 'devise'
  gem 'react-rails'
  gem "font-awesome-rails"
  gem 'foreman'
  
  group :development, :test do
    # Call 'byebug' anywhere in the code to stop execution and get a debugger console
    gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
    # gem 'rspec-rails', '~&gt; 3.8'
    gem 'rspec-rails', git: 'https://github.com/rspec/rspec-rails', branch: "4-0-maintenance"
  end
  
  
  group :development do
    gem 'guard-rspec', require: false
    gem 'listen', '&gt;= 3.0.5', '&lt; 3.2'
    gem 'rb-fsevent', '~&gt; 0.10.3'
    gem 'spring'
    gem 'spring-watcher-listen', '~&gt; 2.0.0'
    gem 'web-console', '&gt;= 3.3.0'
  end
  
  group :test do
    gem 'database_cleaner'
    gem 'factory_bot_rails'
    gem 'faker'
    gem 'shoulda-matchers'
  end
  </code></pre>
  
  <p><strong>routes.rb</strong></p>
  
  <pre><code>    Rails.application.routes.draw do
    devise_for :users
     get 'landing/index'
     get '/index', to: 'landing#index', as: 'index'
  
  
    namespace :api do
      namespace :v1 do
        resources :cocktails do
          put :favourite, on: :member
        end
  
        resources :favourite_cocktails, only: %i[create destroy]
        resources :favourites_dashboard, only: %i[index]
      end
    end
  
    root 'landing#app'
    match '*path', to: 'landing#app', via: :all
  end
  </code></pre>
  
  <p><strong>Favourite_cocktails controller</strong></p>
  
  <pre><code>module Api
    module V1
      class FavouriteCocktailsController &lt; ApplicationController
        skip_before_action :verify_authenticity_token
  
  
        def index
          @favouritecocktail = current_user.cocktails
  
          if user_signed_in? &amp;&amp; @favouritecocktail
            render json: {status: 'SUCCESS', message: 'Loading all Favourite Cocktails', data: @favouritecocktail}, status: :ok
          else
            render json: {}, status: 401
          end
        end
  
        def create
  
          fav = FavouriteCocktail.new(favourite_params) do |c|
            c.user = current_user
          end
  
          if fav.save!
            render json: { message: 'created' }, status: :created
          else
            render json: { errors: fav.errors.full_messages },
             status: :unprocessable_entity
          end
        end
  
        def destroy
          @favouritecocktail = current_user.favourite_cocktails.find_by(cocktail_id: params[:id])
          @favouritecocktail.delete
        end
  
        private
  
        def favourite_params
          params.require(:favourite_cocktail).permit(:cocktail_id)
        end
      end
    end
  end
  
  </code></pre>
  
  <p><strong>Favourite_cocktails factory</strong></p>
  
  <pre><code>FactoryBot.define do
    factory :favourite_cocktail do
      user
      cocktail
    end
  end
  
  </code></pre>
  
  <p><strong>User Factory</strong></p>
  
  <pre><code>FactoryBot.define do
    factory :user do
      username { Faker::Name.name }
      email { Faker::Internet.safe_email }
      password { 'foobar' }
      password_confirmation { 'foobar' }
    end
  
    factory :random_user, class: User do
      username { Faker::Name.name }
      email { Faker::Internet.safe_email }
      password { Faker::Password.password }
      password_confirmation { Faker::Password.password_confirmation }
    end
  end
  
  </code></pre>
  
  <p><strong>Cocktails factory</strong></p>
  
  <pre><code>FactoryBot.define do
    factory :cocktail do
      name { Faker::Restaurant.name }
      description { Faker::Lorem.sentence }
      ingredients { Faker::Lorem.sentence }
      image { Faker::Avatar.image }
    end
  end
  
  </code></pre>
  
  <p><strong>Associations</strong></p>
  
  <p><strong>Favourite_cocktails</strong></p>
  
  <pre><code>class FavouriteCocktail &lt; ApplicationRecord
    belongs_to :user
    belongs_to :cocktail
  
    validates :user_id, uniqueness: { scope: :cocktail_id }
  end
  </code></pre>
  
  <p><strong>User</strong></p>
  
  <pre><code>class User &lt; ApplicationRecord
    # Include default devise modules. Others available are:
    # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
    devise :database_authenticatable, :registerable,
           :recoverable, :rememberable, :validatable
  
    has_many :favourite_cocktails
    has_many :favourites, through: :favourite_cocktails, source: :cocktail
  
    validates :username, presence: true, uniqueness: true, allow_blank: false, length: { minimum: 5 }
    validates :email, presence: true, length: { minimum: 5 }
  end
  
  </code></pre>
  
  <p><strong>cocktail</strong></p>
  
  <pre><code>class Cocktail &lt; ApplicationRecord
    has_many :favourite_cocktails
    has_many :favourited, through: :favourite_cocktails, source: :user
  
    validates :name, presence: true, allow_blank: false, length: { minimum: 5 }
    validates :description, presence: true, allow_blank: false, length: { minimum: 10 }
    validates :ingredients, presence: true, allow_blank: false, length: { minimum: 10 }
    validates :image, presence: true
  end
  
  </code></pre>
  
  <p><strong>RSpec</strong></p>
  
  <p><strong>Favourite Cocktail Request Spec</strong></p>
  
  <pre><code>require 'rails_helper'
  
  RSpec.describe Api::V1::FavouriteCocktailsController, type: :request do
  
    describe 'POST Favourite Cocktails' do
      let!(:users) { FactoryBot.create(:user) }
      let!(:cocktails) { FactoryBot.create_list(:cocktail, 10) }
      let!(:favourite_cocktail) { FactoryBot.create_list(:favourite_cocktail, 10) }
      let(:cocktail_id) { cocktails.first.id }
  
      let(:valid_params) do
        { favourite_cocktail: { cocktail_id: cocktails.first.id } }
      end
  
      before do
        sign_in users
      end
  
      context 'when the request is valid' do
  
        before { post '/api/v1/favourite_cocktails', params: valid_params }
  
        it 'returns status code 201' do
          expect(response).to have_http_status(201)
        end
  
        it 'returns a created status' do
          expect(response).to have_http_status(:created)
        end
  
      end
  
    end
  
    describe 'GET all favourite cocktails' do
  
      let!(:users) { FactoryBot.create(:user) }
      let!(:favourite_cocktail) { FactoryBot.create_list(:favourite_cocktail, 10) }
      let(:cocktail_id) { cocktails.first.id }
  
  
      before do
        sign_in users
        get '/api/v1/favourite_cocktails'
      end
  
      it 'returns HTTP status 200' do
        expect(response).to have_http_status 200
      end
    end
  
  
  
    describe 'DELETE /api/v1/favourite_cocktails/:id' do
      let!(:users) { FactoryBot.create(:user) }
      let!(:cocktails) { FactoryBot.create(:cocktail) }
  
      let!(:favourite_cocktail) { FactoryBot.create_list(:favourite_cocktail, 10, cocktail: cocktails) }
      let(:cocktail_id) { favourite_cocktail.first.id }
  
  
      before do
        sign_in users
      end
  
      before { delete "/api/v1/favourite_cocktails/#{cocktail_id}" }
  
      # thing = create(:thing)
      # delete '/things', :thing =&gt; { :id =&gt; thing.id'}
  
      it 'returns status code 204' do
        expect(response).to have_http_status(204)
      end
    end
  
  end
  </code></pre>
  
  <p>If there are other things you'd like to see to get this working please let me know. Thanks for your help.</p>