1require_relative '../../spec_helper' 2require_relative 'fixtures/classes' 3 4module ModuleSpecs 5 class Parent 6 def method_to_remove; 1; end 7 end 8 9 class First 10 def method_to_remove; 1; end 11 end 12 13 class Second < First 14 def method_to_remove; 2; end 15 end 16end 17 18describe "Module#remove_method" do 19 before :each do 20 @module = Module.new { def method_to_remove; end } 21 end 22 23 ruby_version_is ''...'2.5' do 24 it "is a private method" do 25 Module.should have_private_instance_method(:remove_method, false) 26 end 27 end 28 ruby_version_is '2.5' do 29 it "is a public method" do 30 Module.should have_public_instance_method(:remove_method, false) 31 end 32 end 33 34 it "removes the method from a class" do 35 klass = Class.new do 36 def method_to_remove; 1; end 37 end 38 x = klass.new 39 klass.send(:remove_method, :method_to_remove) 40 x.respond_to?(:method_to_remove).should == false 41 end 42 43 it "removes method from subclass, but not parent" do 44 child = Class.new(ModuleSpecs::Parent) do 45 def method_to_remove; 2; end 46 remove_method :method_to_remove 47 end 48 x = child.new 49 x.respond_to?(:method_to_remove).should == true 50 x.method_to_remove.should == 1 51 end 52 53 it "removes multiple methods with 1 call" do 54 klass = Class.new do 55 def method_to_remove_1; 1; end 56 def method_to_remove_2; 2; end 57 remove_method :method_to_remove_1, :method_to_remove_2 58 end 59 x = klass.new 60 x.respond_to?(:method_to_remove_1).should == false 61 x.respond_to?(:method_to_remove_2).should == false 62 end 63 64 it "accepts multiple arguments" do 65 Module.instance_method(:remove_method).arity.should < 0 66 end 67 68 it "does not remove any instance methods when argument not given" do 69 before = @module.instance_methods(true) + @module.private_instance_methods(true) 70 @module.send :remove_method 71 after = @module.instance_methods(true) + @module.private_instance_methods(true) 72 before.sort.should == after.sort 73 end 74 75 it "returns self" do 76 @module.send(:remove_method, :method_to_remove).should equal(@module) 77 end 78 79 it "raises a NameError when attempting to remove method further up the inheritance tree" do 80 lambda { 81 class Third < ModuleSpecs::Second 82 remove_method :method_to_remove 83 end 84 }.should raise_error(NameError) 85 end 86 87 it "raises a NameError when attempting to remove a missing method" do 88 lambda { 89 class Third < ModuleSpecs::Second 90 remove_method :blah 91 end 92 }.should raise_error(NameError) 93 end 94 95 describe "on frozen instance" do 96 before :each do 97 @frozen = @module.dup.freeze 98 end 99 100 it "raises a #{frozen_error_class} when passed a name" do 101 lambda { @frozen.send :remove_method, :method_to_remove }.should raise_error(frozen_error_class) 102 end 103 104 it "raises a #{frozen_error_class} when passed a missing name" do 105 lambda { @frozen.send :remove_method, :not_exist }.should raise_error(frozen_error_class) 106 end 107 108 it "raises a TypeError when passed a not name" do 109 lambda { @frozen.send :remove_method, Object.new }.should raise_error(TypeError) 110 end 111 112 it "does not raise exceptions when no arguments given" do 113 @frozen.send(:remove_method).should equal(@frozen) 114 end 115 end 116end 117