mocha 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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