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

Commit 79ce192

Browse files
committed
Merge pull request #1596 from rspec/fix-any-instance-private-method-visibility
Mark any_instance proxy methods as private if they were private
1 parent 1c7096f commit 79ce192

File tree

3 files changed

+39
-9
lines changed

3 files changed

+39
-9
lines changed

Changelog.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
### Development
22
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.13.2...3-13-maintennace)
33

4+
Bug Fixes:
5+
6+
* When stubbing methods using the `expect_any_instance_of` or `allow_any_instance_of`
7+
ensure the stubbed method has the same visibility as the real method.
8+
(Jon Rowe, #1596)
9+
410
### 3.13.2 / 2024-10-02
511
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.13.1...v3.13.2)
612

lib/rspec/mocks/any_instance/recorder.rb

+2
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,12 @@ def observe!(method_name)
259259
@observed_methods << method_name
260260
backup_method!(method_name)
261261
recorder = self
262+
method_was_private = @klass.private_method_defined?(method_name)
262263
@klass.__send__(:define_method, method_name) do |*args, &blk|
263264
recorder.playback!(self, method_name)
264265
__send__(method_name, *args, &blk)
265266
end
267+
@klass.__send__(:private, method_name) if method_was_private
266268
@klass.__send__(:ruby2_keywords, method_name) if @klass.respond_to?(:ruby2_keywords, true)
267269
end
268270

spec/rspec/mocks/any_instance_spec.rb

+31-9
Original file line numberDiff line numberDiff line change
@@ -1074,22 +1074,43 @@ def foo; end
10741074
end
10751075

10761076
context "private methods" do
1077-
before :each do
1078-
allow_any_instance_of(klass).to receive(:private_method).and_return(:something)
1077+
before(:example) { allow_any_instance_of(klass).to receive(:private_method).and_return(:something) }
10791078

1080-
verify_all
1079+
let(:object) { klass.new }
1080+
1081+
# The map(&:to_sym) is for legacy Ruby compatability and can be dropped in RSpec 4
1082+
it "maintains the method in the list of private_methods" do
1083+
expect {
1084+
verify_all
1085+
}.to_not change { object.private_methods.map(&:to_sym).include?(:private_method) }.from(true)
10811086
end
10821087

1083-
it "cleans up the backed up method" do
1084-
expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be_falsey
1088+
it "maintains the methods exclusion from the list of public_methods" do
1089+
expect {
1090+
verify_all
1091+
}.to_not change { object.public_methods.map(&:to_sym).include?(:private_method) }.from(false)
10851092
end
10861093

1087-
it "restores a stubbed private method after the spec is run" do
1094+
it "maintains the methods visibility" do
1095+
expect { klass.new.private_method }.to raise_error(NoMethodError)
1096+
expect(klass.new.send(:private_method)).to eq(:something)
10881097
expect(klass.private_method_defined?(:private_method)).to be_truthy
10891098
end
10901099

1091-
it "ensures that the restored method behaves as it originally did" do
1092-
expect(klass.new.send(:private_method)).to eq(:private_method_return_value)
1100+
context "after the spec has run" do
1101+
before(:example) { verify_all }
1102+
1103+
it "cleans up the backed up method" do
1104+
expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be_falsey
1105+
end
1106+
1107+
it "restores a stubbed private method after the spec is run" do
1108+
expect(klass.private_method_defined?(:private_method)).to be_truthy
1109+
end
1110+
1111+
it "ensures that the restored method behaves as it originally did" do
1112+
expect(klass.new.send(:private_method)).to eq(:private_method_return_value)
1113+
end
10931114
end
10941115
end
10951116
end
@@ -1098,7 +1119,7 @@ def foo; end
10981119
context "private methods" do
10991120
before :each do
11001121
expect_any_instance_of(klass).to receive(:private_method).and_return(:something)
1101-
klass.new.private_method
1122+
klass.new.send(:private_method)
11021123

11031124
verify_all
11041125
end
@@ -1109,6 +1130,7 @@ def foo; end
11091130

11101131
it "restores a stubbed private method after the spec is run" do
11111132
expect(klass.private_method_defined?(:private_method)).to be_truthy
1133+
expect(klass.new.private_methods.map(&:to_sym)).to include :private_method
11121134
end
11131135

11141136
it "ensures that the restored method behaves as it originally did" do

0 commit comments

Comments
 (0)