rspec / rspec-mocks

RSpec's 'test double' framework, with support for stubbing and mocking
https://rspec.info
MIT License
1.16k stars 356 forks source link

`expect_any_instance_of(…).not_to receive(…)` makes a private instance method public #1584

Open manueljacob opened 1 month ago

manueljacob commented 1 month ago

Subject of the issue

expect_any_instance_of(…).not_to receive(…) or expect_any_instance_of(…).to receive(…) make a private instance method public. expect(…).not_to receive(…) and expect(…).not_to receive(…) work as intended.

Your environment

Steps to reproduce

Run the following script.

# frozen_string_literal: true

begin
  require "bundler/inline"
rescue LoadError => e
  $stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler"
  raise e
end

gemfile(true) do
  source "https://rubygems.org"

  gem "rspec", "3.13.0" # Activate the gem and version you are reporting the issue against.
end

puts "Ruby version is: #{RUBY_VERSION}"
require 'rspec/autorun'

RSpec.describe 'a private method' do
  let(:klass) do
    Class.new do
      private

      def defined_private_method
      end
    end
  end

  let(:object) { klass.new }

  shared_examples 'behaves like a private method' do
    it 'can’t be called from the outside' do
      expect{object.defined_private_method}.to raise_error "private method `defined_private_method' called for #{object}"
    end

    it 'is included in the list of private methods' do
      expect(object.private_methods).to include :defined_private_method
    end

    it 'is not included in the list of public methods' do
      expect(object.public_methods).not_to include :defined_private_method
    end
  end

  context 'that is not mocked' do
    include_examples 'behaves like a private method'
  end

  context 'mocked with #expect' do
    before do
      expect(object).not_to receive(:defined_private_method)
    end

    include_examples 'behaves like a private method'
  end

  context 'mocked with #expect_any_instance_of' do
    before do
      expect_any_instance_of(klass).not_to receive(:defined_private_method)
    end

    include_examples 'behaves like a private method'
  end
end

Expected behavior

There should be no failures.

Actual behavior

All examples in context 'mocked with #expect_any_instance_of' fail.