Module: RSpock::Helpers::BlockCapture

Defined in:
lib/rspock/helpers/block_capture.rb

Class Method Summary collapse

Class Method Details

.capture(obj, method_name) ⇒ Object

Installs a block-capture wrapper on obj for method_name. Must be called AFTER Mocha's expects/stubs so the wrapper sits in front of whatever Mocha installed.

Returns a lambda that, when called, returns the captured block (or nil if no block was passed).



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
# File 'lib/rspock/helpers/block_capture.rb', line 12

def self.capture(obj, method_name)
  state = { captured: nil }

  if obj.respond_to?(method_name, true)
    # Real objects or objects where Mocha defined the method on
    # the singleton class. Prepend a module so we intercept the
    # call before Mocha's stub (prepend wins over define_singleton_method).
    s = state
    capture_mod = Module.new do
      define_method(method_name) do |*args, **kwargs, &blk|
        s[:captured] = blk
        super(*args, **kwargs, &blk)
      end
    end
    obj.singleton_class.prepend(capture_mod)
  else
    # Mock objects where the method goes through method_missing.
    original_mm = obj.method(:method_missing)
    s = state
    obj.define_singleton_method(:method_missing) do |name, *args, **kwargs, &blk|
      s[:captured] = blk if name == method_name
      original_mm.call(name, *args, **kwargs, &blk)
    end
  end

  -> { state[:captured] }
end