Search code examples
ruby-on-railsrspecrspec-rails

Adding RSpec coverage for a method with if/else logic


So I am fairly new to RSpec and Rails and I've been trying to learn RSpec as much as possible and I am really struggling with implementing coverage for methods that contain logic in them.

The app that I am practicing with uses coverage percentages to make sure I am properly covering the code I am implementing and I am missing coverage on the following method:

def initialize_business
  businesses.each do |business|
    if business.type == 'Restaurant'
      @business_type = Business::Restaurant.new(json_directory: 'restaurant.json')
    elsif business.type = 'Bar'
      @business_type = Business::Bar.new(json_directory: 'bar.json')
    else
      @business_type = Business::Other.new(json_directory: 'other_business.json')
    end
  end
  business_type = @business_type
  initialize_business_creator(business_type)
end

My initial attempt at providing coverage (left out the other unrelated specs) but I struggled to even implement any coverage as I'm too new to RSpec:

describe '#initialize_business' do
    subject do
      described_class.new([business], business_sample_file).
      initialize_business_creator
    end

    it 'assigns a value to @business_type' do
      expect(assigns(@business_type)).to_not be_nil
    end
  end
end

I'm just looking for some help and/or guidance on how to implement specs for a method like this.


Solution

  • You need to create scenarios to test the branches of your code (if, elsif, else)

    What you can do is, you can mock the method which is returning the type to get your desired results.

    For example if you want to test that your if condition is evaluated and the code in that branch is run successfully.

    You can do something like this:

    describe '#initialize_business' do
        subject do
          described_class.new([business], business_sample_file).
          initialize_business_creator
        end
    
        it 'assigns a value to @business_type' do
          expect(assigns(@business_type)).to_not be_nil
        end
        
        context "when business type is 'Restaurant'" do
            before { allow_any_instance_of(Business).to receive(:type).and_return "Restaurant"
        end
    
        it "should create data from restaurant.json" do
            //here you can write expectations for your code inside if statement
    
        end
      end
    end
    

    The line:

    allow_any_instance_of(Business).to receive(:type).and_return "Restaurant"

    will return a "Restaurant" string whenever business.type is called.

    In same way, you can make this method to return other values like "Bar" and check your elsif scenario.