Home > Mobile >  Rails Delayed Jobs testing
Rails Delayed Jobs testing

Time:04-26

I wanted to test a delayed job that in its performs function calls and external API with some data and if successful updates a record in the database.

class IncomeUploadJob < Struct.new(:person)
  def perform

      success, result = PersonService.upload_finances(person.income)
      if success
          rich = RichPeople.new(:name => person.name,
                                :income => person.income,
                                :richness_level => result["richness_level"])
          rich.save!
        end
      else
        Rails.logger.warn("Upload income job failed")
      end
  end
end

I wanted to write a simple test for this where I can just call that method and in the end, after the job is completed I could test the Db for the new record. Some guidance will be greatly appreciated.

CodePudding user response:

Example Rspec test

require 'rails_helper'

describe IncomeUploadJob do
  describe '#perform' do
    let(:person) { create(:person) }

    before { stub_api_call }

    context 'when success' do
      it 'creates RichPeople record' do
        IncomeUploadJob.new.perform
        RichPeople.reload

        expect(RichPeople.count).not_to eq(0)
      end
    end

    def stub_api_call
      stub_request(:post, 'https://apiurl.com/access_token').to_return(
        body: fixture('access_token.json'),
        headers: { 'Content-Type' => 'application/json' }
      )
    end
  end
end

Explanation:

  • let(:person) { create(:person) } this may not require in your case, if required, you can create person factory and create person record
  • You can mock/stub your API calls as I did in stub_api_call method, create fixure file if API response is big otherwise you can directly add it here instead of fixure. You can stub more than one API as per your requirement, I just did one.
  • IncomeUploadJob.new.perform calls the job.

Thanks, let me know if you have any other queries in it

CodePudding user response:

You can use a mock on your service with something like:

describe IncomeUploadJob do
  context 'with successful API request' do
    subject { described_class.perform_now(person) }
 
    let(:person) { create(:person) } # assume you're using Faker
    let(:double_finance_upload) { [true, {"richness_level" => 42} ]}
  
    before do
      expect(PersonService).to receive(:upload_finances).with(person.income).and_return(double_finance_upload)
    end

    it 'creates a new rich person' do
      expect{subject}.to change{RichPeople.count}.by(1)
    end
  end
end
  • Related