Search code examples
ruby-on-railsrspec

The test is successful on an isolated run, it is not successful on a general run of all tests


I have one test pass in isolation, but when I run everything together, it fails. I ran the --bisect flag and this is what it gave me:

The minimal reproduction command is:
  rspec ./spec/requests/api/v1/categories_requests_spec.rb[1:3:1] ./spec/requests/api/v1/categorizations_requests_spec.rb[1:1:1]

Here is the code from these blocks:

spec/requests/api/v1/categories_requests_spec.rb[1:3:1]

describe 'DELETE api/v1/categories/:id' do
    let!(:category) { create :category }
    let(:params) { { id: category.id } }

    subject { delete api_v1_category_path(params) }

    it 'delete category' do
      expect { subject }.to change { Category.count }.by(-1)
      expect(response).to have_http_status(200)
    end
  end

and spec/requests/api/v1/categorizations_requests_spec.rb[1:1:1]

RSpec.describe 'Api::V1::Categorizations', type: :request do
  let(:category) { create :category }
  let(:product) { create :product }

  describe 'POST api/v1/categorizations' do
    let(:params) { { category_id: category.id, product_id: product.id } }
    subject { post api_v1_categorizations_path, params: params }

    it 'create categorization' do
      expect { subject }.to change { Categorization.count }.by(1)
      expect(response).to have_http_status(201)
    end

    context 'does not create a new categorization if it already exists' do
      let!(:categorization) do
        create :categorization, category: category, product: product
      end

      it 'does not create categorization' do
        expect { subject }.not_to(change { Categorization.count })
        expect(response).to have_http_status(422)
      end
    end
  end

end

To be honest, I have no idea what exactly he failed to delete from the database and why the conflict is happening. I tried to rename the category variables by checking that delete api_v1_category_path does not delete the category object created in RSpec.describe' Api::V1::Classifications', type: :request (I output the fabricate-categories identifier to the terminal), but everything is fine. Please help me, I don't understand what the problem is, how do these test cases interfere with each other?

The message of the failed text case itself:

Failures:

  1) Api::V1::Categorizations POST api/v1/categorizations create categorization
     Failure/Error: expect { subject }.to change { Categorization.count }.by(1)
       expected `Categorization.count` to have changed by 1, but was changed by 0
     # ./spec/requests/api/v1/categorizations_requests_spec.rb:15:in `block (3 levels) in <main>'
     # ./spec/spec_helper.rb:100:in `block (3 levels) in <top (required)>'
     # ./spec/spec_helper.rb:99:in `block (2 levels) in <top (required)>'

Solution

  • It's decided! I didn’t fully understand what actually happened, but the error was that in my controller the product variable stored the category ID, and the category variable stored the product ID.

    class Api::V1::CategorizationsController < Api::V1::BaseController
      # POST api/v1/categorizations
      def create
        @product = Category.find(params[:category_id])
        @category = Product.find(params[:product_id])
        @categorization = Categorization.create(category_id: @category.id, product_id: @product.id)
        if @categorization.save
          render jsonapi: @categorization, status: :created, code: '201'
        else
          render jsonapi_errors: @categorization.errors,
                 status: :unprocessable_entity, code: '422'
        end
      end
    end
    

    But I still don't understand why this test in a separate run was successful.