mocha 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README CHANGED
@@ -1,164 +1,35 @@
1
1
  = Mocha
2
2
 
3
- Mocha is a library for mocking and stubbing within tests using a syntax like that of JMock[http://www.jmock.org] and SchMock[http://rubyforge.org/projects/schmock].
3
+ Mocha is a library for mocking and stubbing within a TestCase[http://www.ruby-doc.org/core/classes/Test/Unit.html] using a syntax like that of JMock[http://www.jmock.org], and SchMock[http://rubyforge.org/projects/schmock].
4
4
 
5
- Mocha comes in four parts:
5
+ One of its main advantages is that it allows you to mock and stub methods on _real_ (non-mock) classes and instances. You can for example stub ActiveRecord[http://api.rubyonrails.com/classes/ActiveRecord/Base.html] instance methods like +create+, +save+, +destroy+ and even class methods like +find+ to avoid hitting the database in unit tests. This is a feature that is not currently offered by other Ruby[http://www.ruby-doc.org/] mocking libraries like FlexMock[http://onestepback.org/software/flexmock] and RSpec[http://rspec.rubyforge.org].
6
6
 
7
- 1. Mocha - traditional mock objects with expectations and verification
8
- 2. Stubba - allows mocking and stubbing of methods on real (non-mock) classes
9
- 3. AutoMocha - magically provides mocks in the place of undefined classes
10
- 4. SmartTestCase - allows addition of multiple setup and teardown methods for a Test::Unit::TestCase
7
+ Mocha provides a unified, simple and readable syntax for both traditional mocking and for mocking with non-mock objects.
11
8
 
12
- Stubba and AutoMocha are the main difference between this mocking library and others like FlexMock[http://onestepback.org/software/flexmock] and RSpec[http://rspec.rubyforge.org].
13
-
14
- == Provenance
15
-
16
- Mocha and Stubba have been created by amalgamating a number of techniques developed by me (James[http:blog.floehopper.org]) and my Reevoo[http://www.reevoo.com] colleagues (Ben[http://www.reevoo.com/blogs/bengriffiths/], Chris[http://blog.seagul.co.uk] and Paul[http://po-ru.com]) into a common syntax. They are both in use on real-world Rails[http://www.rubyonrails.org] projects. AutoMocha is more experimental and is at an earlier stage of development. SmartTestCase has been exrtacted from Mocha and Stubba to remove duplication and allow its use in isolation.
9
+ Mocha has been harvested from projects at Reevoo[http://www.reevoo.com] by me (James[http://blog.floehopper.org]) and my colleagues Ben[http://www.reevoo.com/blogs/bengriffiths/], Chris[http://blog.seagul.co.uk] and Paul[http://po-ru.com]. Mocha is in use on real-world Rails[http://www.rubyonrails.org] projects.
17
10
 
18
11
  == Download and Installation
19
12
 
20
- You can download Mocha from here[http://rubyforge.org/projects/mocha] or install it with the following command.
13
+ Install the gem with the following command...
21
14
 
22
- $ gem install mocha
15
+ $ gem install mocha
23
16
 
24
- == Ruby on Rails plugin
17
+ Or install the Rails[http://www.rubyonrails.org] plugin...
25
18
 
26
19
  $ script/plugin install svn://rubyforge.org/var/svn/mocha/trunk
27
20
 
28
- == License
29
-
30
- Copyright Revieworld Ltd. 2006
31
-
32
- You may use, copy and redistribute this library under the same terms as Ruby itself (see http://www.ruby-lang.org/en/LICENSE.txt) or under the MIT license (see http://mocha.rubyforge.org/files/MIT-LICENSE.html).
21
+ Or download Mocha from here - http://rubyforge.org/projects/mocha
33
22
 
34
23
  == Examples
35
24
 
36
- See MochaAcceptanceTest, StubbaAcceptanceTest, AutoMochaAcceptanceTest and unit tests for more examples.
37
-
38
- === Mocha Example
39
-
40
- class Enterprise
41
-
42
- def initialize(dilithium)
43
- @dilithium = dilithium
44
- end
45
-
46
- def go(warp_factor)
47
- warp_factor.times { @dilithium.nuke(:anti_matter) }
48
- end
49
-
50
- end
51
-
52
- require 'test/unit'
53
- require 'rubygems'
54
- require 'mocha'
55
-
56
- class EnterpriseTest < Test::Unit::TestCase
57
-
58
- def test_should_boldly_go
59
- dilithium = mock()
60
- dilithium.expects(:nuke).with(:anti_matter).at_least_once # auto-verified at end of test
61
- enterprise = Enterprise.new(dilithium)
62
- enterprise.go(2)
63
- end
64
-
65
- end
66
-
67
- === Stubba Example
68
-
69
- class Order
70
-
71
- attr_accessor :shipped_on
72
-
73
- def total_cost
74
- line_items.inject(0) { |total, line_item| total + line_item.price } + shipping_cost
75
- end
76
-
77
- def total_weight
78
- line_items.inject(0) { |total, line_item| total + line_item.weight }
79
- end
80
-
81
- def shipping_cost
82
- total_weight * 5 + 10
83
- end
84
-
85
- class << self
25
+ * Quick Start - {Usage Examples}[link:examples/misc.html]
26
+ * Traditional mocking - {Star Trek Example}[link:examples/mocha.html]
27
+ * Setting expectations on real classes - {Order Example}[link:examples/stubba.html]
28
+ * More examples on {Floehopper's Blog}[http://blog.floehopper.org]
29
+ * {Mailing List Archives}[http://rubyforge.org/pipermail/mocha-developer/]
86
30
 
87
- def find_all
88
- # Database.connection.execute('select * from orders...
89
- end
90
-
91
- def number_shipped_since(date)
92
- find_all.select { |order| order.shipped_on > date }.size
93
- end
94
-
95
- def unshipped_value
96
- find_all.inject(0) { |total, order| order.shipped_on ? total : total + order.total_cost }
97
- end
98
-
99
- end
100
-
101
- end
102
-
103
- require 'test/unit'
104
- require 'rubygems'
105
- require 'stubba'
106
-
107
- class OrderTest < Test::Unit::TestCase
108
-
109
- # illustrates stubbing instance method
110
- def test_should_calculate_shipping_cost_based_on_total_weight
111
- order = Order.new
112
- order.stubs(:total_weight).returns(10)
113
- assert_equal 60, order.shipping_cost
114
- end
115
-
116
- # illustrates stubbing class method
117
- def test_should_count_number_of_orders_shipped_after_specified_date
118
- now = Time.now; week_in_secs = 7 * 24 * 60 * 60
119
- order_1 = Order.new; order_1.shipped_on = now - 1 * week_in_secs
120
- order_2 = Order.new; order_2.shipped_on = now - 3 * week_in_secs
121
- Order.stubs(:find_all).returns([order_1, order_2])
122
- assert_equal 1, Order.number_shipped_since(now - 2 * week_in_secs)
123
- end
124
-
125
- # illustrates stubbing instance method for all instances of a class
126
- def test_should_calculate_value_of_unshipped_orders
127
- Order.stubs(:find_all).returns([Order.new, Order.new, Order.new])
128
- Order.any_instance.stubs(:shipped_on).returns(nil)
129
- Order.any_instance.stubs(:total_cost).returns(10)
130
- assert_equal 30, Order.unshipped_value
131
- end
132
-
133
- end
134
-
135
- === AutoMocha Example
136
-
137
- class Article
138
-
139
- attr_reader :id
140
-
141
- def accepted_comments
142
- Comment.find_all_by_article_id(self.id).select { |comment| comment.accepted? }
143
- end
144
-
145
- end
146
-
147
- require 'rubygems'
148
- require 'auto_mocha'
149
- require 'test/unit'
150
-
151
- class OrderTest < Test::Unit::TestCase
152
-
153
- # illustrates stubbing of previously undefined class Comment
154
- def test_should_return_accepted_comments_for_this_article
155
- unaccepted_comment = stub(:accepted? => false)
156
- accepted_comment = stub(:accepted? => true)
157
- comments = [unaccepted_comment, accepted_comment]
158
- Comment.stubs(:find_all_by_article_id).returns(comments)
159
- article = Article.new
160
- assert_equal [accepted_comment], article.accepted_comments
161
- end
162
-
163
- end
31
+ == License
164
32
 
33
+ Copyright Revieworld Ltd. 2006
34
+
35
+ You may use, copy and redistribute this library under the same terms as {Ruby itself}[http://www.ruby-lang.org/en/LICENSE.txt] or under the {MIT license}[http://mocha.rubyforge.org/files/MIT-LICENSE.html].
data/Rakefile CHANGED
@@ -3,6 +3,10 @@ require 'rake/rdoctask'
3
3
  require 'rake/gempackagetask'
4
4
  require 'rake/contrib/sshpublisher'
5
5
 
6
+ module Mocha
7
+ VERSION = "0.3.2"
8
+ end
9
+
6
10
  desc "Default task is currently to run all tests"
7
11
  task :default => :test_all
8
12
 
@@ -17,12 +21,14 @@ Rake::RDocTask.new do |task|
17
21
  task.main = 'README'
18
22
  task.title = 'Mocha'
19
23
  task.rdoc_dir = 'doc'
24
+ task.template = "html_with_google_analytics"
20
25
  task.options << "--line-numbers" << "--inline-source"
21
- task.rdoc_files.include('README', 'RELEASE', 'COPYING', 'MIT-LICENSE', 'agiledox.txt', 'lib/**/*.rb')
26
+ task.rdoc_files.include('README', 'RELEASE', 'COPYING', 'MIT-LICENSE', 'agiledox.txt', 'lib/mocha/auto_verify.rb', 'lib/mocha/mock_methods.rb', 'lib/mocha/expectation.rb', 'lib/stubba/object.rb')
22
27
  end
28
+ task :rdoc => :examples
23
29
 
24
30
  desc "Upload RDoc to RubyForge"
25
- task :publish_rdoc => [:rdoc] do
31
+ task :publish_rdoc => [:rdoc, :examples] do
26
32
  Rake::SshDirPublisher.new("jamesmead@rubyforge.org", "/var/www/gforge-projects/mocha", "doc").upload
27
33
  end
28
34
 
@@ -42,16 +48,36 @@ file 'agiledox.txt' do
42
48
  end
43
49
  end
44
50
 
51
+ desc "Convert example ruby files to syntax-highlighted html"
52
+ task :examples do
53
+ require 'coderay'
54
+ mkdir_p 'doc/examples'
55
+ File.open('doc/examples/coderay.css', 'w') do |output|
56
+ output << CodeRay::Encoders[:html]::CSS.new.stylesheet
57
+ end
58
+ ['mocha', 'stubba', 'misc'].each do |filename|
59
+ File.open("doc/examples/#{filename}.html", 'w') do |file|
60
+ file << "<html>"
61
+ file << "<head>"
62
+ file << %q(<link rel="stylesheet" media="screen" href="coderay.css" type="text/css">)
63
+ file << "</head>"
64
+ file << "<body>"
65
+ file << CodeRay.scan_file("examples/#{filename}.rb").html.div
66
+ file << "</body>"
67
+ file << "</html>"
68
+ end
69
+ end
70
+ end
71
+
45
72
  Gem::manage_gems
46
73
 
47
74
  specification = Gem::Specification.new do |s|
48
75
  s.name = "mocha"
49
76
  s.summary = "Mocking and stubbing library"
50
- s.version = "0.3.1"
77
+ s.version = Mocha::VERSION
51
78
  s.author = 'James Mead'
52
79
  s.description = <<-EOF
53
80
  Mocking and stubbing library with JMock/SchMock syntax, which allows mocking and stubbing of methods on real (non-mock) classes.
54
- Includes auto-mocking which magically provides mocks for undefined classes, facilitating unit tests with no external dependencies.
55
81
  EOF
56
82
  s.email = 'mocha-developer@rubyforge.org'
57
83
  s.homepage = 'http://mocha.rubyforge.org'
@@ -62,11 +88,39 @@ specification = Gem::Specification.new do |s|
62
88
  s.rdoc_options << '--title' << 'Mocha' << '--main' << 'README' << '--line-numbers'
63
89
 
64
90
  s.autorequire = 'mocha'
65
- s.files = FileList['{lib,test}/**/*.rb', '[A-Z]*'].to_a
91
+ s.files = FileList['{lib,test}/**/*.rb', '[A-Z]*'].exclude('TODO').to_a
66
92
  s.test_file = "test/all_tests.rb"
67
93
  end
68
94
 
69
95
  Rake::GemPackageTask.new(specification) do |package|
70
96
  package.need_zip = true
71
97
  package.need_tar = true
72
- end
98
+ end
99
+
100
+ task :verify_user do
101
+ raise "RUBYFORGE_USER environment variable not set!" unless ENV['RUBYFORGE_USER']
102
+ end
103
+
104
+ task :verify_password do
105
+ raise "RUBYFORGE_PASSWORD environment variable not set!" unless ENV['RUBYFORGE_PASSWORD']
106
+ end
107
+
108
+ desc "Publish package files on RubyForge."
109
+ task :publish_packages => [:verify_user, :verify_password, :package] do
110
+ require 'meta_project'
111
+ require 'rake/contrib/xforge'
112
+ release_files = FileList[
113
+ "pkg/mocha-#{Mocha::VERSION}.gem",
114
+ "pkg/mocha-#{Mocha::VERSION}.tgz",
115
+ "pkg/mocha-#{Mocha::VERSION}.zip"
116
+ ]
117
+
118
+ Rake::XForge::Release.new(MetaProject::Project::XForge::RubyForge.new('mocha')) do |release|
119
+ release.user_name = ENV['RUBYFORGE_USER']
120
+ release.password = ENV['RUBYFORGE_PASSWORD']
121
+ release.files = release_files.to_a
122
+ release.release_name = "Mocha #{Mocha::VERSION}"
123
+ release.release_changes = ''
124
+ release.release_notes = ''
125
+ end
126
+ end
@@ -3,5 +3,5 @@ require 'mocha/auto_verify'
3
3
  require 'shared/backtracefilter'
4
4
 
5
5
  class Test::Unit::TestCase
6
- include AutoVerify unless ancestors.include?(AutoVerify)
6
+ include Mocha::AutoVerify unless ancestors.include?(Mocha::AutoVerify)
7
7
  end
@@ -1,46 +1,113 @@
1
1
  require 'mocha/mock'
2
2
 
3
- module AutoVerify
3
+ # Methods added to TestCase allowing creation of mock objects.
4
+ #
5
+ # Mocks created this way will have their expectations automatically verified at the end of the test.
6
+ #
7
+ # See Mocha::MockMethods for methods on mock objects.
8
+ module Mocha
9
+ module AutoVerify
4
10
 
5
- def self.included(base)
6
- base.add_teardown_method(:teardown_mocks)
7
- end
11
+ def self.included(base) # :nodoc:
12
+ base.add_teardown_method(:teardown_mocks)
13
+ end
8
14
 
9
- def mocks
10
- @mocks ||= []
11
- end
15
+ def mocks # :nodoc:
16
+ @mocks ||= []
17
+ end
12
18
 
13
- def reset_mocks
14
- @mocks = nil
15
- end
16
-
17
- def mock(expectations = {})
18
- build_mock_with_expectations(:expects, expectations)
19
- end
19
+ def reset_mocks # :nodoc:
20
+ @mocks = nil
21
+ end
20
22
 
21
- def stub(expectations = {})
22
- build_mock_with_expectations(:stubs, expectations)
23
- end
23
+ # :call-seq: mock(name) -> mock object
24
+ # mock(expected_methods = {}) -> mock object
25
+ # mock(name, expected_methods = {}) -> mock object
26
+ #
27
+ # Creates a mock object.
28
+ #
29
+ # +name+ is a +String+ identifier for the mock object.
30
+ #
31
+ # +expected_methods+ is a +Hash+ with expected method name symbols as keys and corresponding return values as values.
32
+ #
33
+ # Note that (contrary to expectations set up by #stub) these expectations <b>must</b> be fulfilled during the test.
34
+ # def test_product
35
+ # product = mock('ipod_product', :manufacturer => 'ipod', :price => 100)
36
+ # assert_equal 'ipod', product.manufacturer
37
+ # assert_equal 100, product.price
38
+ # # an error will be raised unless both Product#manufacturer and Product#price have been called
39
+ # end
40
+ def mock(*args)
41
+ name, expectations = name_and_expectations_from_args(args)
42
+ build_mock_with_expectations(:expects, expectations, name)
43
+ end
24
44
 
25
- def stub_everything(expectations = {})
26
- build_mock_with_expectations(:stub_everything, expectations)
27
- end
45
+ # :call-seq: stub(name) -> mock object
46
+ # stub(stubbed_methods = {}) -> mock object
47
+ # stub(name, stubbed_methods = {}) -> mock object
48
+ #
49
+ # Creates a mock object.
50
+ #
51
+ # +name+ is a +String+ identifier for the mock object.
52
+ #
53
+ # +stubbed_methods+ is a +Hash+ with stubbed method name symbols as keys and corresponding return values as values.
54
+ #
55
+ # Note that (contrary to expectations set up by #mock) these expectations <b>need not</b> be fulfilled during the test.
56
+ # def test_product
57
+ # product = stub('ipod_product', :manufacturer => 'ipod', :price => 100)
58
+ # assert_equal 'ipod', product.manufacturer
59
+ # assert_equal 100, product.price
60
+ # # an error will not be raised even if Product#manufacturer and Product#price have not been called
61
+ # end
62
+ def stub(*args)
63
+ name, expectations = name_and_expectations_from_args(args)
64
+ build_mock_with_expectations(:stubs, expectations, name)
65
+ end
66
+
67
+ # :call-seq: stub_everything(name) -> mock object
68
+ # stub_everything(stubbed_methods = {}) -> mock object
69
+ # stub_everything(name, stubbed_methods = {}) -> mock object
70
+ #
71
+ # Creates a mock object that accepts calls to any method.
72
+ #
73
+ # By default it will return +nil+ for any method call.
74
+ #
75
+ # +name+ and +stubbed_methods+ work in the same way as for #stub.
76
+ # def test_product
77
+ # product = stub_everything('ipod_product', :price => 100)
78
+ # assert_nil product.manufacturer
79
+ # assert_nil product.any_old_method
80
+ # assert_equal 100, product.price
81
+ # end
82
+ def stub_everything(*args)
83
+ name, expectations = name_and_expectations_from_args(args)
84
+ build_mock_with_expectations(:stub_everything, expectations, name)
85
+ end
28
86
 
29
- def teardown_mocks
30
- mocks.each { |mock| mock.verify { add_assertion } }
31
- reset_mocks
32
- end
87
+ def teardown_mocks # :nodoc:
88
+ mocks.each { |mock| mock.verify { add_assertion } }
89
+ reset_mocks
90
+ end
33
91
 
34
- def build_mock_with_expectations(expectation_type = :expects, expectations = {})
35
- stub_everything = (expectation_type == :stub_everything)
36
- expectation_type = :stubs if expectation_type == :stub_everything
37
- mock = Mocha::Mock.new(stub_everything)
38
- expectations.each do |method, result|
39
- mock.send(expectation_type, method).returns(result)
92
+ def build_mock_with_expectations(expectation_type = :expects, expectations = {}, name = nil) # :nodoc:
93
+ stub_everything = (expectation_type == :stub_everything)
94
+ expectation_type = :stubs if expectation_type == :stub_everything
95
+ mock = Mocha::Mock.new(stub_everything, name)
96
+ expectations.each do |method, result|
97
+ mock.send(expectation_type, method).returns(result)
98
+ end
99
+ mocks << mock
100
+ mock
101
+ end
102
+
103
+ private
104
+
105
+ def name_and_expectations_from_args(args) # :nodoc:
106
+ name = args.first.is_a?(String) ? args.delete_at(0) : nil
107
+ expectations = args.first || {}
108
+ [name, expectations]
40
109
  end
41
- mocks << mock
42
- mock
110
+
43
111
  end
44
112
 
45
- end
46
-
113
+ end
@@ -2,8 +2,11 @@ require 'mocha/infinite_range'
2
2
  require 'mocha/pretty_parameters'
3
3
 
4
4
  module Mocha
5
+ # Methods on expectations returned from Mocha::MockMethods#expects and Mocha::MockMethods#stubs
5
6
  class Expectation
6
7
 
8
+ # :stopdoc:
9
+
7
10
  class InvalidExpectation < Exception; end
8
11
 
9
12
  class AlwaysEqual
@@ -37,47 +40,146 @@ module Mocha
37
40
  end
38
41
  end
39
42
 
43
+ # :startdoc:
44
+
45
+ # :call-seq: times(range) -> expectation
46
+ #
47
+ # Modifies expectation so that the number of calls to the expected method must be within a specific +range+.
48
+ #
49
+ # +range+ can be specified as an exact integer or as a range of integers
50
+ # object = mock()
51
+ # object.expects(:expected_method).times(3)
52
+ # 3.times { object.expected_method } # => verify succeeds
53
+ #
54
+ # object = mock()
55
+ # object.expects(:expected_method).times(3)
56
+ # 2.times { object.expected_method } # => verify fails
57
+ #
58
+ # object = mock()
59
+ # object.expects(:expected_method).times(2..4)
60
+ # 3.times { object.expected_method } # => verify succeeds
61
+ #
62
+ # object = mock()
63
+ # object.expects(:expected_method).times(2..4)
64
+ # object.expected_method # => verify fails
40
65
  def times(range)
41
66
  @count = range
42
67
  self
43
68
  end
44
69
 
70
+ # :call-seq: never -> expectation
71
+ #
72
+ # Modifies expectation so that the expected method must never be called.
73
+ # object = mock()
74
+ # object.expects(:expected_method).never
75
+ # object.expected_method # => verify fails
76
+ #
77
+ # object = mock()
78
+ # object.expects(:expected_method).never
79
+ # object.expected_method # => verify succeeds
45
80
  def never
46
81
  times(0)
47
82
  end
48
83
 
84
+ # :call-seq: at_least(minimum) -> expectation
85
+ #
86
+ # Modifies expectation so that the expected method must be called at least a +minimum+ number of times.
87
+ # object = mock()
88
+ # object.expects(:expected_method).at_least(2)
89
+ # 3.times { object.expected_method } # => verify succeeds
90
+ #
91
+ # object = mock()
92
+ # object.expects(:expected_method).at_least(2)
93
+ # object.expected_method # => verify fails
49
94
  def at_least(minimum)
50
95
  times(Range.at_least(minimum))
51
96
  self
52
97
  end
53
98
 
99
+ # :call-seq: at_least_once() -> expectation
100
+ #
101
+ # Modifies expectation so that the expected method must be called at least once.
102
+ # object = mock()
103
+ # object.expects(:expected_method).at_least_once
104
+ # object.expected_method # => verify succeeds
105
+ #
106
+ # object = mock()
107
+ # object.expects(:expected_method).at_least_once
108
+ # # => verify fails
54
109
  def at_least_once()
55
110
  at_least(1)
56
111
  self
57
112
  end
58
113
 
114
+ # :call-seq: with(*arguments, &parameter_block) -> expectation
115
+ #
116
+ # Modifies expectation so that the expected method must be called with specified +arguments+.
117
+ # object = mock()
118
+ # object.expects(:expected_method).with(:param1, :param2)
119
+ # object.expected_method(:param1, :param2) # => verify succeeds
120
+ #
121
+ # object = mock()
122
+ # object.expects(:expected_method).with(:param1, :param2)
123
+ # object.expected_method(:param3) # => verify fails
124
+ # If a +parameter_block+ is given, the block is called with the parameters passed to the expected method.
125
+ # The expectation is matched if the block evaluates to +true+.
126
+ # object = mock()
127
+ # object.expects(:expected_method).with() { |value| value % 4 == 0 }
128
+ # object.expected_method(16) # => verify succeeds
129
+ #
130
+ # object = mock()
131
+ # object.expects(:expected_method).with() { |value| value % 4 == 0 }
132
+ # object.expected_method(17) # => verify fails
59
133
  def with(*arguments, &parameter_block)
60
134
  @parameters, @parameter_block = arguments, parameter_block
61
135
  class << @parameters; def to_s; join(', '); end; end
62
136
  self
63
137
  end
64
138
 
139
+ # :call-seq: yields(*parameters) -> expectation
140
+ #
141
+ # Modifies expectation so that when the expected method is called, it yields with the specified +parameters+.
142
+ # object = mock()
143
+ # object.expects(:expected_method).yields('result')
144
+ # yielded_value = nil
145
+ # object.expected_method { |value| yielded_value = value }
146
+ # yielded_value # => 'result'
65
147
  def yields(*parameters)
66
148
  @yield = true
67
149
  @parameters_to_yield = parameters
68
150
  self
69
151
  end
70
152
 
153
+ # :call-seq: returns(value) -> expectation
154
+ #
155
+ # Modifies expectation so that when the expected method is called, it returns the specified +value+.
156
+ # object = mock()
157
+ # object.expects(:expected_method).returns('result')
158
+ # object.expected_method # => 'result'
159
+ # If +value+ is a Proc, then expected method will return result of calling Proc.
160
+ # object = mock()
161
+ # results = [111, 222]
162
+ # object.stubs(:expected_method).returns(lambda { results.shift })
163
+ # object.expected_method # => 111
164
+ # object.expected_method # => 222
71
165
  def returns(value)
72
166
  @return_value = value
73
167
  self
74
168
  end
75
169
 
170
+ # :call-seq: raises(exception = RuntimeError, message = nil) -> expectation
171
+ #
172
+ # Modifies expectation so that when the expected method is called, it raises the specified +exception+ with the specified +message+.
173
+ # object = mock()
174
+ # object.expects(:expected_method).raises(Exception, 'message')
175
+ # object.expected_method # => raises exception of class Exception and with message 'message'
76
176
  def raises(exception = RuntimeError, message = nil)
77
177
  @return_value = lambda{ raise exception, message }
78
178
  self
79
179
  end
80
180
 
181
+ # :stopdoc:
182
+
81
183
  def invoke
82
184
  @invoked += 1
83
185
  yield(*@parameters_to_yield) if yield? and block_given?
@@ -99,8 +201,12 @@ module Mocha
99
201
  ":#{@method_name}(#{params.pretty})"
100
202
  end
101
203
 
204
+ # :startdoc:
205
+
102
206
  end
103
207
 
208
+ # :stopdoc:
209
+
104
210
  class Stub < Expectation
105
211
 
106
212
  def verify
@@ -111,14 +217,14 @@ module Mocha
111
217
 
112
218
  class MissingExpectation < Expectation
113
219
 
114
- def initialize(method_name, expectations = [])
220
+ def initialize(method_name, mock, expectations = [])
115
221
  super(method_name)
116
- @expectations = expectations
222
+ @mock, @expectations = mock, expectations
117
223
  @invoked = true
118
224
  end
119
225
 
120
226
  def verify
121
- msg = "Unexpected message #{message}"
227
+ msg = "Unexpected message #{message} sent to #{@mock.mocha_inspect}"
122
228
  msg << "\nSimilar expectations #{similar_expectations.collect { |expectation| expectation.message }.join("\n") }" unless similar_expectations.empty?
123
229
  raise Test::Unit::AssertionFailedError, msg if @invoked
124
230
  end
@@ -128,4 +234,7 @@ module Mocha
128
234
  end
129
235
 
130
236
  end
237
+
238
+ # :startdoc:
239
+
131
240
  end