class SimpleStub::ForInstanceMethod
Stub for instance methods, without any alias_method. This class internally prepends a module into the target class. {#apply} adds a method into the prepended module. {#reset} removes a method from the prepended module.
This class must be stateless for the usecase that the caller of {#apply} and the caller of {#reset} can be different. Both
@stub_user_name = SimpleStub::ForInstanceMethod(User, :name) { 'YusukeIwaki' } @stub_user_name.apply! # Any username is YusukeIwaki here @stub_user_name.reset!
and
stub_user_name = SimpleStub::ForInstanceMethod(User, :name) { 'YusukeIwaki' } stub_user_name.apply! # Any username is YusukeIwaki here stub_user_name = SimpleStub::ForInstanceMethod(User, :name) { 'YusukeIwaki' } stub_user_name.reset!
should work.
Public Class Methods
new(klass, method_name, &impl)
click to toggle source
@param klass [Class] @param method_name [Symbol]
# File lib/simple_stub/for_instance_method.rb, line 33 def initialize(klass, method_name, &impl) raise ArgumentError, "klass must be a Class. #{klass.class} specified." unless klass.is_a?(Class) raise ArgumentError, 'method name must be a Symbol.' unless method_name.is_a?(Symbol) @klass = klass @method_name = method_name @impl = impl end
Public Instance Methods
apply()
click to toggle source
Safer version of {#apply!} Nothing happens when the stub is already applied.
# File lib/simple_stub/for_instance_method.rb, line 44 def apply return if stub_defined? apply_stub end
apply!()
click to toggle source
Apply the stub. If the stub is already applied, raises error.
# File lib/simple_stub/for_instance_method.rb, line 51 def apply! raise AlreadyAppliedError, "The stub for #{@klass}##{@method_name} is already applied" if stub_defined? apply_stub end
reset()
click to toggle source
Safer version of {#reset!}. Nothing happens when the stub is already applied.
# File lib/simple_stub/for_instance_method.rb, line 59 def reset return unless stub_defined? reset_stub end
reset!()
click to toggle source
Remove the stub and revert to the original implementation. If the stub is not applied or already reset, raise error.
# File lib/simple_stub/for_instance_method.rb, line 66 def reset! raise NotAppliedError, "The stub for #{@klass}##{@method_name} is already applied" unless stub_defined? reset_stub end
Private Instance Methods
apply_stub()
click to toggle source
# File lib/simple_stub/for_instance_method.rb, line 74 def apply_stub raise ArgumentError, 'Block must be given for applying stub' unless @impl # define_method is private on Ruby <= 2.4 impl_module.send(:define_method, @method_name, &@impl) end
create_and_apply_impl_module()
click to toggle source
# File lib/simple_stub/for_instance_method.rb, line 94 def create_and_apply_impl_module Module.new.tap do |mod| # Name the module here ForInstanceMethod.const_set(impl_module_name, mod) @klass.prepend(mod) end end
impl_module()
click to toggle source
# File lib/simple_stub/for_instance_method.rb, line 86 def impl_module impl_module_or_nil || create_and_apply_impl_module end
impl_module_name()
click to toggle source
# File lib/simple_stub/for_instance_method.rb, line 107 def impl_module_name @impl_module_name ||= "StubImpl#{klass_digest}" end
impl_module_or_nil()
click to toggle source
# File lib/simple_stub/for_instance_method.rb, line 90 def impl_module_or_nil ForInstanceMethod.const_get(impl_module_name) if ForInstanceMethod.const_defined?(impl_module_name) end
klass_digest()
click to toggle source
# File lib/simple_stub/for_instance_method.rb, line 103 def klass_digest @klass_digest ||= Digest::SHA256.hexdigest(@klass.to_s) end
reset_stub()
click to toggle source
# File lib/simple_stub/for_instance_method.rb, line 81 def reset_stub # remove_method is private on Ruby <= 2.4 impl_module.send(:remove_method, @method_name) end
stub_defined?()
click to toggle source
# File lib/simple_stub/for_instance_method.rb, line 111 def stub_defined? # Avoid creating module just in asking if stub exists. impl_module_or_nil&.method_defined?(@method_name) end