From 1ea05148f1f7fefffbd1b606760cad2b1c18c9a4 Mon Sep 17 00:00:00 2001 From: Markus Schirp Date: Sat, 27 Apr 2013 18:21:38 +0200 Subject: [PATCH] Add specs for singleton methods matcher Also cleanup some dead code --- lib/mutant/matcher/methods.rb | 82 ++++++++++--------- .../matcher/methods/singleton/each_spec.rb | 53 ++++++++++++ 2 files changed, 95 insertions(+), 40 deletions(-) create mode 100644 spec/unit/mutant/matcher/methods/singleton/each_spec.rb diff --git a/lib/mutant/matcher/methods.rb b/lib/mutant/matcher/methods.rb index 6b0edc4a..fed9a38c 100644 --- a/lib/mutant/matcher/methods.rb +++ b/lib/mutant/matcher/methods.rb @@ -24,8 +24,6 @@ module Mutant self end - private - # Return method matcher class # # @return [Class:Matcher::Method] @@ -36,6 +34,22 @@ module Mutant self.class::MATCHER end + # Return methods + # + # @return [Enumerable] + # + # @api private + # + def methods + candidate_names.each_with_object([]) do |name, methods| + method = access(name) + methods << method if method.owner == candidate_scope + end + end + memoize :methods + + private + # Emit matches for method # # @param [UnboundMethod, Method] method @@ -50,20 +64,6 @@ module Mutant end end - # Return methods - # - # @return [Enumerable] - # - # @api private - # - def methods - candidates.each_with_object([]) do |name, methods| - method = access(name) - methods << method if method.owner == scope - end - end - memoize :methods - # Return candidate names # # @param [Object] object @@ -72,8 +72,8 @@ module Mutant # # @api private # - def candidates - object = self.scope + def candidate_names + object = candidate_scope names = object.public_instance_methods(false) + object.private_instance_methods(false) + @@ -81,9 +81,19 @@ module Mutant names.sort end + # Return candidate scope + # + # @return [Class, Module] + # + # @api private + # + abstract_method :candidate_scope + class Singleton < self MATCHER = Matcher::Method::Singleton + private + # Return method for name # # @param [Symbol] method_name @@ -96,27 +106,24 @@ module Mutant scope.method(method_name) end - private - - # Return singleton methods defined on scope + # Return candidate scope # - # @param [Class|Module] scope - # - # @return [Enumerable] + # @return [Class] # # @api private # - def method_names - singleton_class = scope.singleton_class - candidate_names.sort.reject do |name| - name.to_sym == :__class_init__ - end + def candidate_scope + scope.singleton_class end + memoize :candidate_scope, :freezer => :noop + end class Instance < self MATCHER = Matcher::Method::Instance + private + # Return method for name # # @param [Symbol] method_name @@ -129,21 +136,16 @@ module Mutant scope.instance_method(method_name) end - private - - # Return instance methods names of scope - # - # @param [Class|Module] scope - # - # @return [Enumerable] + # Return candidate scope # + # @return [Class, Module] + # # @api private # - def method_names - scope = self.scope - return [] unless scope.kind_of?(Module) - candidate_names.sort + def candidate_scope + scope end + end end end diff --git a/spec/unit/mutant/matcher/methods/singleton/each_spec.rb b/spec/unit/mutant/matcher/methods/singleton/each_spec.rb new file mode 100644 index 00000000..88e4277a --- /dev/null +++ b/spec/unit/mutant/matcher/methods/singleton/each_spec.rb @@ -0,0 +1,53 @@ +require 'spec_helper' + +describe Mutant::Matcher::Methods::Singleton, '#each' do + let(:object) { described_class.new(Foo) } + + subject { object.each { |matcher| yields << matcher } } + + let(:yields) { [] } + + module Bar + def method_d + end + + def method_e + end + end + + class Foo + extend Bar + + def self.method_a + end + + def self.method_b + end + class << self; protected :method_b; end + + def self.method_c + end + private_class_method :method_c + + end + + let(:subject_a) { mock('Subject A') } + let(:subject_b) { mock('Subject B') } + let(:subject_c) { mock('Subject C') } + + let(:subjects) { [subject_a, subject_b, subject_c] } + + before do + matcher = Mutant::Matcher::Method::Singleton + matcher.stub(:new).with(Foo, Foo.method(:method_a)).and_return([subject_a]) + matcher.stub(:new).with(Foo, Foo.method(:method_b)).and_return([subject_b]) + matcher.stub(:new).with(Foo, Foo.method(:method_c)).and_return([subject_c]) + end + + it 'should yield expected subjects' do + subject + yields.should eql(subjects) + end + + it_should_behave_like 'an #each method' +end