Class: FlexMock

Inherits:
Object
  • Object
show all
Extended by:
ArgumentTypes
Defined in:
lib/flexmock/core.rb,
lib/flexmock/rspec.rb,
lib/flexmock/recorder.rb,
lib/flexmock/composite.rb,
lib/flexmock/validators.rb,
lib/flexmock/expectation.rb,
lib/flexmock/partial_mock.rb,
lib/flexmock/argument_types.rb,
lib/flexmock/mock_container.rb,
lib/flexmock/argument_matchers.rb,
lib/flexmock/core_class_methods.rb,
lib/flexmock/expectation_director.rb,
lib/flexmock/test_unit_integration.rb,
lib/flexmock/default_framework_adapter.rb

Overview

FlexMock is a flexible mock object framework for supporting testing.

FlexMock has a simple interface that’s easy to remember, and leaves the hard stuff to all those other mock object implementations.

Basic Usage:

m = flexmock("name")
m.should_receive(:upcase).with("stuff").
  and_return("STUFF")
m.should_receive(:downcase).with(String).
  and_return { |s| s.downcase }.once

With Test::Unit Integration:

class TestSomething < Test::Unit::TestCase
  include FlexMock::TestCase

  def test_something
    m = flexmock("name")
    m.should_receive(:hi).and_return("Hello")
    m.hi
  end
end

Note: When using Test::Unit integeration, don’t forget to include FlexMock::TestCase. Also, if you override teardown, make sure you call super.

Defined Under Namespace

Modules: ArgumentTypes, MockContainer, TestCase Classes: AnyMatcher, AtLeastCountValidator, AtMostCountValidator, CompositeExpectation, CountValidator, DefaultFrameworkAdapter, EqualMatcher, ExactCountValidator, Expectation, ExpectationDirector, ExpectationRecorder, PartialMock, ProcMatcher, RSpecFrameworkAdapter, Recorder, TestUnitFrameworkAdapter

Constant Summary collapse

ANY =
AnyMatcher.new

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ArgumentTypes

any, eq, on

Constructor Details

#initialize(name = "unknown") ⇒ FlexMock

Create a FlexMock object with the given name. The name is used in error messages.



50
51
52
53
54
55
56
57
58
59
# File 'lib/flexmock/core.rb', line 50

def initialize(name="unknown")
  @mock_name = name
  @expectations = Hash.new
  @allocated_order = 0
  @mock_current_order = 0
  @mock_container = nil
  @mock_groups = {}
  @ignore_missing = false
  @verified = false
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args, &block) ⇒ Object

Handle missing methods by attempting to look up a handler.



99
100
101
102
103
104
105
106
107
108
# File 'lib/flexmock/core.rb', line 99

def method_missing(sym, *args, &block)
  mock_wrap do
    if handler = @expectations[sym]
      args << block  if block_given?
      handler.call(*args)
    else
      super(sym, *args, &block)  unless @ignore_missing
    end
  end
end

Class Attribute Details

.framework_adapterObject (readonly)

Returns the value of attribute framework_adapter.



16
17
18
# File 'lib/flexmock/core_class_methods.rb', line 16

def framework_adapter
  @framework_adapter
end

Instance Attribute Details

#mock_containerObject

Returns the value of attribute mock_container.



46
47
48
# File 'lib/flexmock/core.rb', line 46

def mock_container
  @mock_container
end

#mock_current_orderObject

Returns the value of attribute mock_current_order.



46
47
48
# File 'lib/flexmock/core.rb', line 46

def mock_current_order
  @mock_current_order
end

#mock_groupsObject (readonly)

Returns the value of attribute mock_groups.



45
46
47
# File 'lib/flexmock/core.rb', line 45

def mock_groups
  @mock_groups
end

#mock_nameObject (readonly)

Returns the value of attribute mock_name.



45
46
47
# File 'lib/flexmock/core.rb', line 45

def mock_name
  @mock_name
end

Class Method Details

.check(msg, &block) ⇒ Object

Check will assert the block returns true. If it doesn’t, an assertion failure is triggered with the given message.



87
88
89
# File 'lib/flexmock/core_class_methods.rb', line 87

def check(msg, &block)  # :nodoc:
  FlexMock.framework_adapter.assert_block(msg, &block)
end

.format_args(sym, args) ⇒ Object

Class method to format a method name and argument list as a nice looking string.



77
78
79
80
81
82
83
# File 'lib/flexmock/core_class_methods.rb', line 77

def format_args(sym, args)  # :nodoc:
  if args
    "#{sym}(#{args.collect { |a| a.inspect }.join(', ')})"
  else
    "#{sym}(*args)"
  end
end

.should_receive(args) ⇒ Object

:call-seq:

should_receive(args) { |symbol| ... }

This method provides common handling for the various should_receive argument lists. It sorts out the differences between symbols, arrays and hashes, and identifies the method names specified by each. As each method name is identified, create a mock expectation for it using the supplied block.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/flexmock/core_class_methods.rb', line 26

def should_receive(args)  # :nodoc:
  result = CompositeExpectation.new
  args.each do |arg|
    case arg
    when Hash
      arg.each do |k,v|
        result.add(yield(k.to_sym).and_return(v))
      end
    when Symbol, String
      result.add(yield(arg.to_sym))
    end
  end
  result
end

.use(*names) ⇒ Object

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.



61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/flexmock/core_class_methods.rb', line 61

def use(*names)
  names = ["unknown"] if names.empty?
  got_excecption = false
  mocks = names.collect { |n| new(n) }
  yield(*mocks)
rescue Exception => ex
  got_exception = true
  raise
ensure
  mocks.each do |mock|
    mock.mock_verify     unless got_exception
  end
end

Instance Method Details

#method(sym) ⇒ Object

Override the built-in method to include the mocked methods.



119
120
121
122
123
124
125
126
127
# File 'lib/flexmock/core.rb', line 119

def method(sym)
  @expectations[sym] || super
rescue NameError => ex
  if @ignore_missing
    proc { }
  else
    raise ex
  end
end

#mock_allocate_orderObject

Allocation a new order number from the mock.



87
88
89
90
# File 'lib/flexmock/core.rb', line 87

def mock_allocate_order
  @auto_allocate = true
  @allocated_order += 1
end

#mock_handle(sym, expected_count = nil, &block) ⇒ Object

Handle all messages denoted by sym by calling the given block and passing any parameters to the block. If we know exactly how many calls are to be made to a particular method, we may check that by passing in the number of expected calls as a second paramter.



66
67
68
# File 'lib/flexmock/core.rb', line 66

def mock_handle(sym, expected_count=nil, &block) # :nodoc:
  self.should_receive(sym).times(expected_count).returns(&block)
end

#mock_respond_to?Object

Save the original definition of respond_to? for use a bit later.



111
# File 'lib/flexmock/core.rb', line 111

alias mock_respond_to? respond_to?

#mock_teardownObject

Teardown and infrastructure setup for this mock.



83
84
# File 'lib/flexmock/core.rb', line 83

def mock_teardown
end

#mock_verifyObject

Verify that each method that had an explicit expected count was actually called that many times.



72
73
74
75
76
77
78
79
80
# File 'lib/flexmock/core.rb', line 72

def mock_verify
  return if @verified
  @verified = true
  mock_wrap do
    @expectations.each do |sym, handler|
      handler.mock_verify
    end
  end
end

#respond_to?(sym) ⇒ Boolean

Override the built-in respond_to? to include the mocked methods.

Returns:

  • (Boolean)


114
115
116
# File 'lib/flexmock/core.rb', line 114

def respond_to?(sym)
  super || (@expectations[sym] ? true : @ignore_missing)
end

#should_expect {|Recorder.new(self)| ... } ⇒ Object

Declare that the mock object should expect methods by providing a recorder for the methods and having the user invoke the expected methods in a block. Further expectations may be applied the result of the recording call.

Example Usage:

mock.should_expect do |record|
  record.add(Integer, 4) { |a, b|
    a + b
  }.at_least.once

Yields:



170
171
172
# File 'lib/flexmock/core.rb', line 170

def should_expect
  yield Recorder.new(self)
end

#should_ignore_missingObject Also known as: mock_ignore_missing

Ignore all undefined (missing) method calls.



93
94
95
# File 'lib/flexmock/core.rb', line 93

def should_ignore_missing
  @ignore_missing = true
end

#should_receive(*args) ⇒ Object

:call-seq:

mock.should_receive(:method_name)
mock.should_receive(:method1, method2, ...)
mock.should_receive(:meth1 => result1, :meth2 => result2, ...)

Declare that the mock object should receive a message with the given name.

If more than one method name is given, then the mock object should expect to receive all the listed melthods. If a hash of method name/value pairs is given, then the each method will return the associated result. Any expectations applied to the result of should_receive will be applied to all the methods defined in the argument list.

An expectation object for the method name is returned as the result of this method. Further expectation constraints can be added by chaining to the result.

See Expectation for a list of declarators that can be used.



148
149
150
151
152
153
154
155
156
# File 'lib/flexmock/core.rb', line 148

def should_receive(*args)
  FlexMock.should_receive(args) do |sym|
    @expectations[sym] ||= ExpectationDirector.new(sym)
    result = Expectation.new(self, sym)
    @expectations[sym] << result
    override_existing_method(sym) if mock_respond_to?(sym)
    result
  end
end