Class: RBS::UnitTest::Spy::WrapSpy

Inherits:
Object
  • Object
show all
Defined in:
lib/rbs/unit_test/spy.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(object:, method_name:) ⇒ WrapSpy

Returns a new instance of WrapSpy.



23
24
25
26
27
# File 'lib/rbs/unit_test/spy.rb', line 23

def initialize(object:, method_name:)
  @callback = -> (_) { }
  @object = object
  @method_name = method_name
end

Instance Attribute Details

#callbackObject

Returns the value of attribute callback.



19
20
21
# File 'lib/rbs/unit_test/spy.rb', line 19

def callback
  @callback
end

#method_nameObject (readonly)

Returns the value of attribute method_name.



21
22
23
# File 'lib/rbs/unit_test/spy.rb', line 21

def method_name
  @method_name
end

#objectObject (readonly)

Returns the value of attribute object.



20
21
22
# File 'lib/rbs/unit_test/spy.rb', line 20

def object
  @object
end

Instance Method Details

#wrapped_objectObject



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
# File 'lib/rbs/unit_test/spy.rb', line 29

def wrapped_object
  spy = self #: WrapSpy[untyped]

  Class.new(BasicObject) do
    # @type self: Class

    define_method(:method_missing) do |name, *args, &block|
      spy.object.__send__(name, *args, &block)
    end

    define_method(
      spy.method_name,
      _ = -> (*args, &block) do
        return_value = nil
        exception = nil
        block_calls = [] #: Array[Test::ArgumentsReturn]

        spy_block = if block
                      Object.new.instance_eval do |fresh|
                        proc = -> (*block_args) do
                          block_exn = nil
                          block_return = nil

                          begin
                            block_return = if self.equal?(fresh)
                                            # no instance eval
                                            block.call(*block_args)
                                          else
                                            self.instance_exec(*block_args, &block)
                                          end
                          rescue Exception => exn
                            block_exn = exn
                          end

                          if block_exn
                            block_calls << Test::ArgumentsReturn.exception(
                              arguments: block_args,
                              exception: block_exn
                            )
                          else
                            block_calls << Test::ArgumentsReturn.return(
                              arguments: block_args,
                              value: block_return
                            )
                          end

                          if block_exn
                            raise block_exn
                          else
                            block_return
                          end
                        end #: Proc

                        proc.ruby2_keywords
                      end
                    end

        begin
          if spy_block
            return_value = spy.object.__send__(spy.method_name, *args) do |*a, **k, &b|
              spy_block.call(*a, **k, &b)
            end
          else
            return_value = spy.object.__send__(spy.method_name, *args, &spy_block)
          end
        rescue ::Exception => exn
          exception = exn
        end

        return_value

      ensure
        call =
          case
          when exception
            Test::ArgumentsReturn.exception(
              arguments: args,
              exception: exception
            )
          when return_value
            Test::ArgumentsReturn.return(
              arguments: args,
              value: return_value
            )
          else
            # break
            Test::ArgumentsReturn.break(arguments: args)
          end
        trace = RBS::Test::CallTrace.new(
          method_name: spy.method_name,
          method_call: call,
          block_calls: block_calls,
          block_given: block != nil
        )

        spy.callback.call(trace)

        if exception
          spy.object.__send__(:raise, exception)
        end
      end.ruby2_keywords
    )
  end.allocate()
end