Skip to content

Commit

Permalink
Remove ModuleMethod#method_exists?
Browse files Browse the repository at this point in the history
This is similar to the change in commit
8f58edd.

Commit e87c03b made
`ModuleMethod#method_exists?` redundant by changing the implementation
of `ClassMethod#hide_original_method` so that it uses
`ClassMethod#method_visibility` instead.

This introduced a subtle change in behaviour due to the difference in
`ModuleMethod#method_exists?` and `ClassMethod#method_visibility`. The
former would return false if the method being stubbed was on `Kernel` or
`Object` while the latter will return true in those cases. This gist
illustrates the difference -
https://gist.github.com/chrisroos/12a1b032b95664448c9e987132f33988.

Practically, this meant that _some_ stubbed module methods (those
defined on Kernel and Object) wouldn't have had the correct visibility
set. The tests added in this commit ensure we don't introduce
regressions in future. The tests for the visibility of the protected and
private methods failed prior to commit
e87c03b. I confirmed this by checking
our the commit before that (`git co
e87c03b~`) and running these new tests.
  • Loading branch information
chrisroos committed Apr 20, 2018
1 parent 12d9ce7 commit fe1d49d
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 8 deletions.
8 changes: 0 additions & 8 deletions lib/mocha/module_method.rb
Expand Up @@ -3,14 +3,6 @@
module Mocha

class ModuleMethod < ClassMethod

def method_exists?(method)
return true if stubbee.public_methods(false).include?(method)
return true if stubbee.protected_methods(false).include?(method)
return true if stubbee.private_methods(false).include?(method)
return false
end

end

end
Expand Up @@ -72,4 +72,67 @@ def my_instance_method
ensure
Kernel.module_eval { remove_method :my_instance_method }
end

def test_should_stub_public_module_method_and_leave_it_unchanged_after_test
Kernel.module_eval do
def my_instance_method
:original_return_value
end
public :my_instance_method
end
mod = Module.new
assert_snapshot_unchanged(mod) do
test_result = run_as_test do
mod.stubs(:my_instance_method).returns(:new_return_value)
assert_method_visibility mod, :my_instance_method, :public
assert_equal :new_return_value, mod.my_instance_method
end
assert_passed(test_result)
end
assert_equal :original_return_value, mod.my_instance_method
ensure
Kernel.module_eval { remove_method :my_instance_method }
end

def test_should_stub_protected_module_method_and_leave_it_unchanged_after_test
Kernel.module_eval do
def my_instance_method
:original_return_value
end
protected :my_instance_method
end
mod = Module.new
assert_snapshot_unchanged(mod) do
test_result = run_as_test do
mod.stubs(:my_instance_method).returns(:new_return_value)
assert_method_visibility mod, :my_instance_method, :protected
assert_equal :new_return_value, mod.send(:my_instance_method)
end
assert_passed(test_result)
end
assert_equal :original_return_value, mod.send(:my_instance_method)
ensure
Kernel.module_eval { remove_method :my_instance_method }
end

def test_should_stub_private_module_method_and_leave_it_unchanged_after_test
Kernel.module_eval do
def my_instance_method
:original_return_value
end
private :my_instance_method
end
mod = Module.new
assert_snapshot_unchanged(mod) do
test_result = run_as_test do
mod.stubs(:my_instance_method).returns(:new_return_value)
assert_method_visibility mod, :my_instance_method, :private
assert_equal :new_return_value, mod.send(:my_instance_method)
end
assert_passed(test_result)
end
assert_equal :original_return_value, mod.send(:my_instance_method)
ensure
Kernel.module_eval { remove_method :my_instance_method }
end
end

0 comments on commit fe1d49d

Please sign in to comment.