Why in Rspec $stdout and STDOUT behaves differently?

I have the below Ruby class, and and test which works with this piece of code.

require 'logger'

class MyAddKlass
  attr_reader :data

  def my_method(x)
    @data = x * 2

    logger = Logger.new($stdout)
    logger.info @data
  end
end

My Rspec code. This code I wrote basically to test how and_call_original but I stepped into something which now became my primary interest to know first.

# frozen_string_literal: true
require_relative '../my_add_klass'

describe MyAddKlass do
  it 'calls the original method' do
    obj = described_class.new

    allow_any_instance_of(Logger).to receive(:info).and_call_original
    expect { obj.my_method(5) }.to output(/.*10/).to_stdout
  end
end

result of the test is green…

 bundle exec rspec ./spec/my_add_klass_spec.rb
.

Finished in 0.04966 seconds (files took 0.40982 seconds to load)
1 example, 0 failures

Now once, I replace $stdout with STDOUT, my test fails.

 bundle exec rspec ./spec/my_add_klass_spec.rb
I, [2024-09-11T00:01:38.039070 #13801]  INFO -- : 10
F

Failures:

  1) MyAddKlass calls the original method
     Failure/Error: expect { obj.my_method(5) }.to output(/.*10/).to_stdout

       expected block to output /.*10/ to stdout, but output nothing
       Diff:
       @@ -1 +1 @@
       -/.*10/
       +""

     # ./spec/my_add_klass_spec.rb:9:in `block (2 levels) in <top (required)>'

Finished in 0.05945 seconds (files took 0.13727 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/my_add_klass_spec.rb:5 # MyAddKlass calls the original method

Why this code behaving differently with STDOUT and $stdout?

1 Like