File: double_definition_create.rb

package info (click to toggle)
ruby-rr 3.1.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,424 kB
  • sloc: ruby: 11,405; makefile: 7
file content (143 lines) | stat: -rw-r--r-- 5,622 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
module RR
  module DoubleDefinitions
    class DoubleDefinitionCreate # :nodoc
      extend(Module.new do
        def default_double_injection_strategy
          @default_double_injection_strategy ||= lambda do |double_injection_create|
            Strategies::DoubleInjection::Instance.new(double_injection_create)
          end
        end

        def set_default_double_injection_strategy(strategy_lambda)
          original_strategy_lambda = default_double_injection_strategy
          begin
            @default_double_injection_strategy = strategy_lambda
            yield
          ensure
            @default_double_injection_strategy = original_strategy_lambda
          end
        end
      end)

      attr_reader :subject, :verification_strategy, :implementation_strategy, :double_injection_strategy
      NO_SUBJECT = Object.new

      include Space::Reader

      def initialize
        @verification_strategy = Strategies::Verification::Stub.new(self)
        @implementation_strategy = Strategies::Implementation::Reimplementation.new(self)
        @double_injection_strategy = self.class.default_double_injection_strategy.call(self)
      end

      def call(method_name, args, kwargs, &handler)
        definition = DoubleDefinition.new(self)
        verification_strategy.call(definition, method_name, args, kwargs, handler)
        implementation_strategy.call(definition, method_name, args, kwargs, handler)
        double_injection_strategy.call(definition, method_name, args, kwargs, handler)
        definition
      end

      def root_subject
        subject
      end

      def method_name
        @verification_strategy.method_name
      end

      module StrategySetupMethods
        def no_subject?
          subject.__id__ === NO_SUBJECT.__id__
        end

      protected
        def add_verification_strategy(verification_strategy_class, subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
          add_strategy(subject, method_name, definition_eval_block) do
            self.verification_strategy = verification_strategy_class.new(self)
          end
        end

        def add_implementation_strategy(implementation_strategy_class, subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
          add_strategy(subject, method_name, definition_eval_block) do
            self.implementation_strategy = implementation_strategy_class.new(self)
          end
        end

        def add_double_injection_strategy(double_injection_strategy_class, subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
          add_strategy(subject, method_name, definition_eval_block) do
            self.double_injection_strategy = double_injection_strategy_class.new(self)
          end
        end

        def add_strategy(subject, method_name, definition_eval_block)
          if method_name && definition_eval_block
            raise ArgumentError, "Cannot pass in a method name and a block"
          end
          @subject = subject
          yield
          # TODO: Allow hash argument to simulate a Struct.
          if no_subject?
            self
          elsif method_name
            # TODO: Pass in arguments.
            call(method_name, [], {})
          else
            DoubleDefinitionCreateBlankSlate.new(self, &definition_eval_block)
          end
        end

        def verification_strategy=(verification_strategy)
          @verification_strategy = verification_strategy
          verification_strategy
        end

        def implementation_strategy=(implementation_strategy)
          @implementation_strategy = implementation_strategy
        end

        def double_injection_strategy=(double_injection_strategy)
          @double_injection_strategy = double_injection_strategy
        end
      end
      include StrategySetupMethods

      class DoubleDefinitionCreateError < Errors::RRError
      end

      ## Verification Strategies

      include ::RR::DoubleDefinitions::Strategies::StrategyMethods

      def mock(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
        self.add_verification_strategy(::RR::DoubleDefinitions::Strategies::Verification::Mock, subject, method_name, &definition_eval_block)
      end

      def stub(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
        self.add_verification_strategy(::RR::DoubleDefinitions::Strategies::Verification::Stub, subject, method_name, &definition_eval_block)
      end

      def dont_allow(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
        self.add_verification_strategy(::RR::DoubleDefinitions::Strategies::Verification::DontAllow, subject, method_name, &definition_eval_block)
      end

      ## Implementation Strategies

      def proxy(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
        self.add_implementation_strategy(::RR::DoubleDefinitions::Strategies::Implementation::Proxy, subject, method_name, &definition_eval_block)
      end

      def strong(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
        self.add_implementation_strategy(::RR::DoubleDefinitions::Strategies::Implementation::StronglyTypedReimplementation, subject, method_name, &definition_eval_block)
      end

      ## DoubleInjection Strategies

      def instance_of(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
        self.add_double_injection_strategy(::RR::DoubleDefinitions::Strategies::DoubleInjection::AnyInstanceOf, subject, method_name, &definition_eval_block)
      end
      alias_method :any_instance_of, :instance_of
      alias_method :all_instances_of, :instance_of
    end
  end
end