Module: MuchStub

Defined in:
lib/much-stub.rb,
lib/much-stub/call.rb,
lib/much-stub/version.rb,
lib/much-stub/call_spy.rb

Defined Under Namespace

Modules: ParameterList Classes: Call, CallSpy, Stub

Constant Summary collapse

StubError =
Class.new(ArgumentError)
NotStubbedError =
Class.new(StubError)
StubArityError =
Class.new(StubError) do
  def initialize(method, args, method_name:, backtrace:)
    msg = "arity mismatch on `#{method_name}`: " \
          "expected #{number_of_args(method.arity)}, " \
          "called with #{args.size}"

    super(msg)
    set_backtrace(Array(backtrace).map(&:to_s))
  end

  private

  def number_of_args(arity)
    if arity < 0
      "at least #{(arity + 1).abs}"
    else
      arity
    end
  end
end
NullStub =
Class.new do
  def teardown
    # no-op
  end
end
VERSION =
"0.1.8"

Class Method Summary collapse

Class Method Details

.arity_matches?(method, args) ⇒ Boolean

Returns:

  • (Boolean)


17
18
19
20
21
22
23
24
# File 'lib/much-stub.rb', line 17

def self.arity_matches?(method, args)
  # mandatory args
  return true if method.arity == args.size
  # variable args
  return true if method.arity < 0 && args.size >= (method.arity + 1).abs

  false
end

.call(*args, &block) ⇒ Object



32
33
34
# File 'lib/much-stub.rb', line 32

def self.call(*args, &block)
  stub(*args, &block)
end

.on_call(*args, &on_call_block) ⇒ Object



40
41
42
# File 'lib/much-stub.rb', line 40

def self.on_call(*args, &on_call_block)
  stub_on_call(*args, &on_call_block)
end

.spy(obj, *meths, **return_values) ⇒ Object



76
77
78
79
80
81
82
83
84
# File 'lib/much-stub.rb', line 76

def self.spy(obj, *meths, **return_values)
  MuchStub::CallSpy.new(**return_values).call_spy_tap do |spy|
    meths.each do |meth|
      stub(obj, meth) do |*args, &block|
        spy.__send__(meth, *args, &block)
      end
    end
  end
end

.stub(obj, meth, &block) ⇒ Object



26
27
28
29
30
# File 'lib/much-stub.rb', line 26

def self.stub(obj, meth, &block)
  key = stub_key(obj, meth)
  stubs[key] ||= MuchStub::Stub.new(obj, meth, caller_locations)
  stubs[key].tap{ |s| s.do = block }
end

.stub_key(obj, meth) ⇒ Object



13
14
15
# File 'lib/much-stub.rb', line 13

def self.stub_key(obj, meth)
  MuchStub::Stub.key(obj, meth)
end

.stub_on_call(*args, &on_call_block) ⇒ Object



36
37
38
# File 'lib/much-stub.rb', line 36

def self.stub_on_call(*args, &on_call_block)
  stub(*args).on_call(&on_call_block)
end

.stub_send(obj, meth, *args, &block) ⇒ Object



53
54
55
56
57
58
59
60
# File 'lib/much-stub.rb', line 53

def self.stub_send(obj, meth, *args, &block)
  orig_caller = caller_locations
  stub =
    stubs.fetch(MuchStub::Stub.key(obj, meth)) do
      raise NotStubbedError, "`#{meth}` not stubbed.", orig_caller.map(&:to_s)
    end
  stub.call_method(args, &block)
end

.stubsObject



9
10
11
# File 'lib/much-stub.rb', line 9

def self.stubs
  @stubs ||= {}
end

.tap(obj, meth, &tap_block) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/much-stub.rb', line 62

def self.tap(obj, meth, &tap_block)
  stub(obj, meth) do |*args, &block|
    stub_send(obj, meth, *args, &block).tap do |value|
      tap_block&.call(value, *args, &block)
    end
  end
end

.tap_on_call(obj, meth, &on_call_block) ⇒ Object



70
71
72
73
74
# File 'lib/much-stub.rb', line 70

def self.tap_on_call(obj, meth, &on_call_block)
  tap(obj, meth) do |value, *args, &block|
    on_call_block&.call(value, MuchStub::Call.new(*args, &block))
  end
end

.unstub(obj, meth) ⇒ Object



44
45
46
47
# File 'lib/much-stub.rb', line 44

def self.unstub(obj, meth)
  key = stub_key(obj, meth)
  (stubs.delete(key) || MuchStub::NullStub.new).teardown
end

.unstub!Object



49
50
51
# File 'lib/much-stub.rb', line 49

def self.unstub!
  stubs.keys.each{ |key| stubs.delete(key).teardown }
end