`any_instance_of` does not restore method on JRuby
Created by: marcotc
Subject of the issue
A special combination of any_instance_of
calls can prevent rspec-mocks
from properly restoring the originally mocked method method during it cleanup step. I'm only able to observe this on JRuby.
Your environment
- Ruby version: jruby 9.2.11.1
- rspec-mocks version: 3.9.1
Steps to reproduce
# 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.9.0'
gem 'rspec-mocks', '3.9.1'
end
require 'rspec/autorun'
puts "Ruby version is: #{RUBY_VERSION}"
STDERR.puts 'You need JRuby to reproduce this issue!' unless RSpec::Support::Ruby.jruby?
RSpec.describe do
it do
clazz = Class.new do
prepend Module.new
def foo
end
end
allow_any_instance_of(clazz).to receive(:foo)
RSpec::Mocks.space.reset_all
expect_any_instance_of(clazz).to_not receive(:foo)
RSpec::Mocks.space.reset_all
clazz.new.foo
end
end
Expected behavior
No failures:
1 example, 0 failures
Actual behavior
Failures:
1)
Failure/Error: clazz.new.foo
NoMethodError:
undefined method `foo' for #<#<Class:0x1d008e61>:0x29db008c>
Did you mean? fork
# rspec-mock-issue.rb:39:in `block in rspec-mock-issue.rb'
Finished in 0.02769 seconds (files took 0.15631 seconds to load)
1 example, 1 failure
Preliminary investigation
My semi-educated guess is that the issue lies in this code block: https://github.com/rspec/rspec-mocks/blob/v3.9.1/lib/rspec/mocks/any_instance/recorder.rb#L202-L222
Forcing alias_method method_name, alias_method_name
to when running on JRuby in that code block "solves" the problem from my example. I unfortunately wasn't able process how the comment included in that snippet linked is applying to our case, so I'm not 100% confident that this is the correct solution.