File: verifying_double.rb

package info (click to toggle)
ruby-rspec 3.12.0c0e1m1s0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 6,752 kB
  • sloc: ruby: 69,818; sh: 1,861; makefile: 99
file content (121 lines) | stat: -rw-r--r-- 3,393 bytes parent folder | download
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
RSpec::Support.require_rspec_mocks 'verifying_proxy'

module RSpec
  module Mocks
    # @private
    module VerifyingDouble
      def respond_to?(message, include_private=false)
        return super unless null_object?

        method_ref = __mock_proxy.method_reference[message]

        case method_ref.visibility
        when :public    then true
        when :private   then include_private
        when :protected then include_private || RUBY_VERSION.to_f < 2.0
        else !method_ref.unimplemented?
        end
      end

      def method_missing(message, *args, &block)
        # Null object conditional is an optimization. If not a null object,
        # validity of method expectations will have been checked at definition
        # time.
        if null_object?
          if @__sending_message == message
            __mock_proxy.ensure_implemented(message)
          else
            __mock_proxy.ensure_publicly_implemented(message, self)
          end

          __mock_proxy.validate_arguments!(message, args)
        end

        super
      end

      # Redefining `__send__` causes ruby to issue a warning.
      old, $VERBOSE = $VERBOSE, nil
      def __send__(name, *args, &block)
        @__sending_message = name
        super
      ensure
        @__sending_message = nil
      end
      $VERBOSE = old

      def send(name, *args, &block)
        __send__(name, *args, &block)
      end

      def initialize(doubled_module, *args)
        @doubled_module = doubled_module

        possible_name = args.first
        name = if String === possible_name || Symbol === possible_name
                 args.shift
               end

        super(name, *args)
        @__sending_message = nil
      end
    end

    # A mock providing a custom proxy that can verify the validity of any
    # method stubs or expectations against the public instance methods of the
    # given class.
    #
    # @private
    class InstanceVerifyingDouble
      include TestDouble
      include VerifyingDouble

      def __build_mock_proxy(order_group)
        VerifyingProxy.new(self, order_group,
                           @doubled_module,
                           InstanceMethodReference
        )
      end
    end

    # An awkward module necessary because we cannot otherwise have
    # ClassVerifyingDouble inherit from Module and still share these methods.
    #
    # @private
    module ObjectVerifyingDoubleMethods
      include TestDouble
      include VerifyingDouble

      def as_stubbed_const(options={})
        ConstantMutator.stub(@doubled_module.const_to_replace, self, options)
        self
      end

    private

      def __build_mock_proxy(order_group)
        VerifyingProxy.new(self, order_group,
                           @doubled_module,
                           ObjectMethodReference
        )
      end
    end

    # Similar to an InstanceVerifyingDouble, except that it verifies against
    # public methods of the given object.
    #
    # @private
    class ObjectVerifyingDouble
      include ObjectVerifyingDoubleMethods
    end

    # Effectively the same as an ObjectVerifyingDouble (since a class is a type
    # of object), except with Module in the inheritance chain so that
    # transferring nested constants to work.
    #
    # @private
    class ClassVerifyingDouble < Module
      include ObjectVerifyingDoubleMethods
    end
  end
end