Skip to content
This repository has been archived by the owner on Nov 30, 2024. It is now read-only.

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

Closed
manueljacob opened this issue Jul 23, 2024 · 1 comment · Fixed by #1596
Closed

Comments

@manueljacob
Copy link

manueljacob commented Jul 23, 2024

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

  • Ruby versions: 2.3.8, 2.4.10, 2.5.9, 2.6.10, 2.7.8, 3.0.7, 3.1.6, 3.2.4, 3.3.4 (for the latter, the reproducer script has to be changed slightly to account for the changed NoMethodError message)
  • rspec-mocks version: 3.13.1

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.

@JonRowe
Copy link
Member

JonRowe commented Oct 2, 2024

Thanks for reporting this, apologies for the delay in looking at it but can you give #1596 a spin to see if it solves your issue?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants