File: core_class_methods.rb

package info (click to toggle)
ruby-flexmock 3.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 836 kB
  • sloc: ruby: 7,572; makefile: 6
file content (145 lines) | stat: -rw-r--r-- 4,264 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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env ruby

#---
# Copyright 2003-2013 by Jim Weirich (jim.weirich@gmail.com).
# All rights reserved.

# Permission is granted for use, copying, modification, distribution,
# and distribution of modified versions of this work as long as the
# above copyright notice is included.
#+++

require 'flexmock/noop'
require 'flexmock/mock_container'

class FlexMock
  class << self
    attr_reader :framework_adapter

    # Class method to make sure that verify is called at the end of a
    # test.  One mock object will be created for each name given to
    # the use method.  The mocks will be passed to the block as
    # arguments.  If no names are given, then a single anonymous mock
    # object will be created.
    #
    # At the end of the use block, each mock object will be verified
    # to make sure the proper number of calls have been made.
    #
    # Usage:
    #
    #   FlexMock.use("name") do |mock|    # Creates a mock named "name"
    #     mock.should_receive(:meth).
    #       returns(0).once
    #   end                               # mock is verified here
    #
    # NOTE: If you include FlexMock::TestCase into your test case
    # file, you can create mocks that will be automatically verified in
    # the test teardown by using the +flexmock+ method.
    #
    def use(*names)
      names = ["unknown"] if names.empty?
      container = UseContainer.new
      mocks = names.collect { |n| container.flexmock(n) }
      yield(*mocks)
    rescue Exception => _
      container.got_exception = true
      raise
    ensure
      container.flexmock_teardown
    end

    FORBID_MOCKING = :__flexmock_forbid_mocking

    # Forbid mock calls to happen while the block is being evaluated
    #
    # @param [Object] mocking_forbidden_return the return value that should be
    #   used if a mocking call has happened. If no mocking calls happened,
    #   returns the return value of the block
    def forbid_mocking(mocking_forbidden_return = nil)
      current, Thread.current[FORBID_MOCKING] =
          Thread.current[FORBID_MOCKING], true

      catch(FORBID_MOCKING) do
        return yield
      end
      mocking_forbidden_return

    ensure
      Thread.current[FORBID_MOCKING] = current
    end

    # Verify that mocking is allowed in the current context. Throws if it is
    # not.
    def verify_mocking_allowed!
      if Thread.current[FORBID_MOCKING]
        throw FORBID_MOCKING
      end
    end

    # Class method to format a method name and argument list as a nice
    # looking string.
    def format_call(sym, args, kw)  # :nodoc:
      "#{sym}(#{format_args(args, kw)})"
    end

    # Class method to format a list of args (the part between the
    # parenthesis).
    def format_args(args, kw)
      args =
        if args
          args = args.map do |a|
            FlexMock.forbid_mocking("<recursive call to mocked method in #inspect>") do
              a.inspect
            end
          end
          args.join(', ')
        else
          "*args"
        end

      kw =
        if kw.kind_of? HashMatcher
          kw.inspect
        elsif kw && !kw.empty?
          kw = kw.transform_values do |v|
            FlexMock.forbid_mocking("<recursive call to mocked method in #inspect>") do
              v.inspect
            end
          end
          kw.map { |k, v| "#{k}: #{v}" }.join(', ')
        elsif kw.nil?
          # Don't append **kwargs to signature if ruby version < 3
          # in order to not break existing code still on ruby2
          "**kwargs" unless RUBY_VERSION < "3"
        end

      [(args unless args.empty?), kw].compact.join(", ")
    end

    # Check will assert the block returns true.  If it doesn't, an
    # assertion failure is triggered with the given message.
    def check(msg, &block)  # :nodoc:
      if FlexMock.framework_adapter.respond_to?(:check)
        FlexMock.framework_adapter.check(msg, &block)
      else
        FlexMock.framework_adapter.make_assertion(msg, &block)
      end
    end

  end

  # Container object to be used by the FlexMock.use method.
  class UseContainer
    include MockContainer

    attr_accessor :got_exception

    def initialize
      @got_exception = false
    end

    def passed?
      ! got_exception
    end
  end
end