Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stub method shared tests #458

Open
wants to merge 33 commits into
base: main
Choose a base branch
from

Conversation

nitishr
Copy link
Contributor

@nitishr nitishr commented Jan 6, 2020

Extract StubMethodSharedTests module to check stubbing of public, protected and private methods on Module, Class, Instance, and AnyInstance under various conditions. The only difference in each case is the method_owner and the callee, and sometimes the stubbee or alias_method?. The shared module allows us specify just the varying parts of the fixture and makes the commonality of the checks more apparent and easier to understand, and to reason about scenarios across all types of stubbees more easily.

Rubocop approves, too, since we could get rid of most of Lint/DuplicateMethod disables.

end

def test_should_stub_method_and_leave_it_unchanged_after_test
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines -14 to -134
def self.public(*args); end
end
instance = klass.new
run_as_test do
klass.any_instance.stubs(:my_instance_method).returns(:new_return_value)
end
assert(instance.public_methods(false).any? { |m| m.to_s == 'my_instance_method' })
assert_equal :original_return_value, instance.my_instance_method
end

def test_should_leave_stubbed_public_method_unchanged_after_test_when_it_was_originally_private_in_owning_module
module_with_private_method = Module.new do
def my_included_method
:original_return_value
end
private :my_included_method
end
klass = Class.new do
include module_with_private_method
public :my_included_method
end
instance = klass.new
test_result = run_as_test do
klass.any_instance.stubs(:my_included_method).returns(:new_return_value)
assert_equal :new_return_value, instance.my_included_method
end
assert_passed(test_result)
assert_equal :original_return_value, instance.my_included_method
end

def test_should_leave_stubbed_protected_method_unchanged_after_test
klass = Class.new do
def my_instance_method
:original_return_value
end
protected :my_instance_method
def self.protected(*args); end

def my_unprotected_instance_method
my_instance_method
end
end
instance = klass.new
run_as_test do
klass.any_instance.stubs(:my_instance_method).returns(:new_return_value)
end
assert(instance.protected_methods(false).any? { |m| m.to_s == 'my_instance_method' })
assert_equal :original_return_value, instance.my_unprotected_instance_method
end

def test_should_stub_protected_method_within_test
klass = Class.new do
def my_instance_method
:original_return_value
end
protected :my_instance_method
def self.protected(*args); end

def my_unprotected_instance_method
my_instance_method
end
end
instance = klass.new
test_result = run_as_test do
klass.any_instance.stubs(:my_instance_method).returns(:new_return_value)
assert_method_visibility instance, :my_instance_method, :protected
end
assert_passed(test_result)
end

def test_should_leave_stubbed_private_method_unchanged_after_test
klass = Class.new do
def my_instance_method
:original_return_value
end
private :my_instance_method
def self.private(*args); end
end
instance = klass.new
run_as_test do
klass.any_instance.stubs(:my_instance_method).returns(:new_return_value)
end
assert(instance.private_methods(false).any? { |m| m.to_s == 'my_instance_method' })
assert_equal :original_return_value, instance.send(:my_instance_method)
end

def test_should_stub_private_method_within_test
klass = Class.new do
def my_instance_method
:original_return_value
end
private :my_instance_method
def self.private(*args); end
end
instance = klass.new
test_result = run_as_test do
klass.any_instance.stubs(:my_instance_method).returns(:new_return_value)
assert_method_visibility instance, :my_instance_method, :private
end
assert_passed(test_result)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All except test_should_leave_stubbed_public_method_unchanged_after_test_when_it_was_originally_private_in_owning_module covered by https://github.com/freerange/mocha/pull/458/files#diff-2d503cd32084bef97bc2b3e3256412c7R3-R15

Comment on lines -150 to -208
def test_should_be_able_to_stub_a_public_superclass_method
superklass = Class.new do
def my_superclass_method
:original_return_value
end
public :my_superclass_method
end
klass = Class.new(superklass)
instance = klass.new
test_result = run_as_test do
klass.any_instance.stubs(:my_superclass_method).returns(:new_return_value)
assert_method_visibility instance, :my_superclass_method, :public
assert_equal :new_return_value, instance.my_superclass_method
end
assert_passed(test_result)
assert(instance.public_methods(true).any? { |m| m.to_s == 'my_superclass_method' })
assert(klass.public_methods(false).none? { |m| m.to_s == 'my_superclass_method' })
assert_equal :original_return_value, instance.my_superclass_method
end

def test_should_be_able_to_stub_a_protected_superclass_method
superklass = Class.new do
def my_superclass_method
:original_return_value
end
protected :my_superclass_method
end
klass = Class.new(superklass)
instance = klass.new
test_result = run_as_test do
klass.any_instance.stubs(:my_superclass_method).returns(:new_return_value)
assert_method_visibility instance, :my_superclass_method, :protected
assert_equal :new_return_value, instance.send(:my_superclass_method)
end
assert_passed(test_result)
assert(instance.protected_methods(true).any? { |m| m.to_s == 'my_superclass_method' })
assert(klass.protected_methods(false).none? { |m| m.to_s == 'my_superclass_method' })
assert_equal :original_return_value, instance.send(:my_superclass_method)
end

def test_should_be_able_to_stub_a_private_superclass_method
superklass = Class.new do
def my_superclass_method
:original_return_value
end
private :my_superclass_method
end
klass = Class.new(superklass)
instance = klass.new
test_result = run_as_test do
klass.any_instance.stubs(:my_superclass_method).returns(:new_return_value)
assert_method_visibility instance, :my_superclass_method, :private
assert_equal :new_return_value, instance.send(:my_superclass_method)
end
assert_passed(test_result)
assert(instance.private_methods(true).any? { |m| m.to_s == 'my_superclass_method' })
assert(klass.private_methods(false).none? { |m| m.to_s == 'my_superclass_method' })
assert_equal :original_return_value, instance.send(:my_superclass_method)
end
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines -45 to -63
def test_should_leave_stubbed_public_method_unchanged_after_test_when_it_was_originally_private_in_owning_module
module_with_private_method = Module.new do
def my_included_method
:original_return_value
end
private :my_included_method
end
klass = Class.new do
include module_with_private_method
public :my_included_method
end
instance = klass.new
test_result = run_as_test do
klass.any_instance.stubs(:my_included_method).returns(:new_return_value)
assert_equal :new_return_value, instance.my_included_method
end
assert_passed(test_result)
assert_equal :original_return_value, instance.my_included_method
end
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -1,78 +1,13 @@
require File.expand_path('../acceptance_test_helper', __FILE__)
require File.expand_path('../stub_method_shared_tests', __FILE__)

class StubClassMethodDefinedOnClassTest < Mocha::TestCase
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -1,67 +1,13 @@
require File.expand_path('../acceptance_test_helper', __FILE__)
require File.expand_path('../stub_method_shared_tests', __FILE__)

class StubInstanceMethodDefinedOnSingletonClassTest < Mocha::TestCase
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -1,70 +1,13 @@
require File.expand_path('../acceptance_test_helper', __FILE__)
require File.expand_path('../stub_method_shared_tests', __FILE__)

class StubInstanceMethodDefinedOnSuperclassTest < Mocha::TestCase
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -1,38 +1,19 @@
require File.expand_path('../acceptance_test_helper', __FILE__)
require File.expand_path('../stub_method_shared_tests', __FILE__)

unless Mocha::PRE_RUBY_V19
class StubMethodDefinedOnModuleAndAliasedTest < Mocha::TestCase
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines -15 to -77
def test_should_stub_method_within_test
mod = Module.new do
def self.my_module_method
:original_return_value
end
end
test_result = run_as_test do
mod.stubs(:my_module_method).returns(:new_return_value)
assert_equal :new_return_value, mod.my_module_method
end
assert_passed(test_result)
end

def test_should_leave_stubbed_public_method_unchanged_after_test
mod = Module.new do
class << self
def my_module_method
:original_return_value
end
public :my_module_method
end
end
run_as_test do
mod.stubs(:my_module_method).returns(:new_return_value)
end
assert(mod.public_methods(false).any? { |m| m.to_s == 'my_module_method' })
assert_equal :original_return_value, mod.my_module_method
end

def test_should_leave_stubbed_protected_method_unchanged_after_test
mod = Module.new do
class << self
def my_module_method
:original_return_value
end
protected :my_module_method
def my_unprotected_module_method
my_module_method
end
end
end
run_as_test do
mod.stubs(:my_module_method).returns(:new_return_value)
end
assert(mod.protected_methods(false).any? { |m| m.to_s == 'my_module_method' })
assert_equal :original_return_value, mod.my_unprotected_module_method
end

def test_should_leave_stubbed_private_method_unchanged_after_test
mod = Module.new do
class << self
def my_module_method
:original_return_value
end
private :my_module_method
end
end
run_as_test do
mod.stubs(:my_module_method).returns(:new_return_value)
end
assert(mod.private_methods(false).any? { |m| m.to_s == 'my_module_method' })
assert_equal :original_return_value, mod.send(:my_module_method)
end
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -88,25 +24,6 @@ def self.my_module_method
assert_equal 0, mod.mocha.__expectations__.length
end

def test_should_be_able_to_stub_a_superclass_method
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleted since it's checking nothing more than stubbing of a non-existent method. The module (mod) doesn't 'inherit' the supermod singleton method simply by including supermod.

... making it identical to protected and private method cases
This will allow us to reuse StubInstanceMethodSharedTests in
StubInstanceMethodDefinedOnClassTest (and perhaps others)
This allows us to reuse StubInstanceMethodSharedTests for checking stubbing on a
Module and stubbing on an object
This will allow us to reuse StubInstanceMethodSharedTests in
StubInstanceMethodDefinedOnSingletonClass as instead of creating an instance
from a class there, we obtain the (singleton) class from the instance.
...since class methods are just instance methods of the singleton class of class
This will allow us to, for instance, stub a method on a superclass but check the
stubbed method on its child
... since it is now used for instance as well as class methods
... and delete test_should_stub_method_within_test as covered by checks
in StubMethodSharedTests
delete test_should_stub_*_method_within_test as already covered by checks in
StubMethodSharedTests
... while moving them from stub_any_instance_method_test to
stub_any_instance_method_defined_on_superclass_test
It wasn't checking stubbing of a supeclass or even a supermodule method.
self.my_superclass_method from supermod isn't inherited/included in mod.
So, all that it checked was that you could stub a non-existent module method.
... to DRY up assert_snapshot_unchanged + run_as_test + assert_passed combo
@nitishr nitishr force-pushed the stub-method-shared-tests branch from dd3c458 to 18c8c49 Compare February 16, 2020 20:47
@floehopper floehopper changed the base branch from master to main July 24, 2020 16:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant