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; end # no-op
end
VERSION =
"0.1.5"

Class Method Summary collapse

Class Method Details

.arity_matches?(method, args) ⇒ Boolean

Returns:

  • (Boolean)


15
16
17
18
19
# File 'lib/much-stub.rb', line 15

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

.call(*args, &block) ⇒ Object



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

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

.on_call(*args, &on_call_block) ⇒ Object



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

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

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



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

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

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



21
22
23
24
25
# File 'lib/much-stub.rb', line 21

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

.stub_key(obj, meth) ⇒ Object



11
12
13
# File 'lib/much-stub.rb', line 11

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

.stub_on_call(*args, &on_call_block) ⇒ Object



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

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

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



48
49
50
51
52
53
54
# File 'lib/much-stub.rb', line 48

def self.stub_send(obj, meth, *args, &block)
  orig_caller = caller_locations
  stub = self.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



7
8
9
# File 'lib/much-stub.rb', line 7

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

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



56
57
58
59
60
61
62
# File 'lib/much-stub.rb', line 56

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

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



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

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

.unstub(obj, meth) ⇒ Object



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

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

.unstub!Object



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

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