mocha 0.1.2 → 0.2.0
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 +11 -15
- data/RELEASE +51 -0
- data/Rakefile +27 -3
- data/TODO +5 -10
- data/lib/auto_mocha.rb +1 -0
- data/lib/mocha.rb +6 -1
- data/lib/mocha/auto_verify.rb +41 -0
- data/lib/smart_test_case.rb +5 -0
- data/lib/smart_test_case/multiple_setup_and_teardown.rb +115 -0
- data/lib/stubba.rb +6 -1
- data/lib/stubba/{stubba.rb → central.rb} +1 -1
- data/lib/stubba/setup_and_teardown.rb +19 -0
- data/test/active_record_test_case.rb +36 -0
- data/test/all_tests.rb +30 -51
- data/test/auto_mock_acceptance_test.rb +0 -1
- data/test/mocha/auto_verify_test.rb +49 -0
- data/test/mocha_acceptance_test.rb +8 -22
- data/test/smart_test_case/multiple_setup_and_teardown_test.rb +91 -0
- data/test/stubba/any_instance_method_test.rb +4 -3
- data/test/stubba/{stubba_test.rb → central_test.rb} +9 -8
- data/test/stubba/class_method_test.rb +1 -2
- data/test/stubba/object_test.rb +29 -44
- data/test/stubba/setup_and_teardown_test.rb +76 -0
- data/test/stubba_integration_test.rb +17 -17
- metadata +13 -7
- data/lib/stubba/test_case.rb +0 -65
- data/test/stubba/test_case_test.rb +0 -41
- data/test/stubba_replacer.rb +0 -13
data/README
CHANGED
@@ -2,21 +2,22 @@
|
|
2
2
|
|
3
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].
|
4
4
|
|
5
|
-
Mocha comes in
|
5
|
+
Mocha comes in four parts:
|
6
6
|
|
7
7
|
1. Mocha - traditional mock objects with expectations and verification
|
8
8
|
2. Stubba - allows mocking and stubbing of methods on real (non-mock) classes
|
9
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
|
10
11
|
|
11
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].
|
12
13
|
|
13
14
|
== Provenance
|
14
15
|
|
15
|
-
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.
|
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.
|
16
17
|
|
17
18
|
== Download and Installation
|
18
19
|
|
19
|
-
You can download Mocha from here[http://rubyforge.org/projects/mocha] or install
|
20
|
+
You can download Mocha from here[http://rubyforge.org/projects/mocha] or install it with the following command.
|
20
21
|
|
21
22
|
$ gem install mocha
|
22
23
|
|
@@ -44,20 +45,17 @@ See MochaAcceptanceTest, StubbaAcceptanceTest, AutoMochaAcceptanceTest and unit
|
|
44
45
|
|
45
46
|
end
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
48
|
+
require 'rubygems'
|
49
|
+
require 'mocha'
|
50
|
+
require 'test/unit'
|
50
51
|
|
51
52
|
class EnterpriseTest < Test::Unit::TestCase
|
52
53
|
|
53
|
-
include Mocha
|
54
|
-
|
55
54
|
def test_should_boldly_go
|
56
|
-
dilithium =
|
57
|
-
dilithium.expects(:nuke).with(:anti_matter).at_least_once
|
55
|
+
dilithium = mock()
|
56
|
+
dilithium.expects(:nuke).with(:anti_matter).at_least_once # auto-verified at end of test
|
58
57
|
enterprise = Enterprise.new(dilithium)
|
59
58
|
enterprise.go(2)
|
60
|
-
dilithium.verify
|
61
59
|
end
|
62
60
|
|
63
61
|
end
|
@@ -148,12 +146,10 @@ See MochaAcceptanceTest, StubbaAcceptanceTest, AutoMochaAcceptanceTest and unit
|
|
148
146
|
|
149
147
|
class OrderTest < Test::Unit::TestCase
|
150
148
|
|
151
|
-
include Mocha
|
152
|
-
|
153
149
|
# illustrates stubbing of previously undefined class Comment
|
154
150
|
def test_should_return_accepted_comments_for_this_article
|
155
|
-
unaccepted_comment =
|
156
|
-
accepted_comment =
|
151
|
+
unaccepted_comment = stub(:accepted? => false)
|
152
|
+
accepted_comment = stub(:accepted? => true)
|
157
153
|
comments = [unaccepted_comment, accepted_comment]
|
158
154
|
Comment.stubs(:find_all_by_article_id).returns(comments)
|
159
155
|
article = Article.new
|
data/RELEASE
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
= 0.2.0
|
2
|
+
|
3
|
+
* Small change to SetupAndTeardown#teardown_stubs suggested by Luke Redpath (http://www.lukeredpath.co.uk) to allow use of Stubba with RSpec (http://rspec.rubyforge.org).
|
4
|
+
* Reorganized directory structure and extracted addition of setup and teardown methods into SmartTestCase mini-library.
|
5
|
+
* Addition of auto-verify for Mocha (but not Stubba). This means there is more significance in the choice of expects or stubs in that any expects on a mock will automatically get verified.
|
6
|
+
|
7
|
+
So instead of...
|
8
|
+
|
9
|
+
wotsit = Mocha.new
|
10
|
+
wotsit.expects(:thingummy).with(5).returns(10)
|
11
|
+
doobrey = Doobrey.new(wotsit)
|
12
|
+
doobrey.hoojamaflip
|
13
|
+
wotsit.verify
|
14
|
+
|
15
|
+
you need to do...
|
16
|
+
|
17
|
+
wotsit = mock()
|
18
|
+
wotsit.expects(:thingummy).with(5).returns(10)
|
19
|
+
doobrey = Doobrey.new(wotsit)
|
20
|
+
doobrey.hoojamaflip
|
21
|
+
# no need to verify
|
22
|
+
|
23
|
+
There are also shortcuts as follows...
|
24
|
+
|
25
|
+
instead of...
|
26
|
+
|
27
|
+
wotsit = Mocha.new
|
28
|
+
wotsit.expects(:thingummy).returns(10)
|
29
|
+
wotsit.expects(:summat).returns(25)
|
30
|
+
|
31
|
+
you can have...
|
32
|
+
|
33
|
+
wotsit = mock(:thingummy => 5, :summat => 25)
|
34
|
+
|
35
|
+
and instead of...
|
36
|
+
|
37
|
+
wotsit = Mocha.new
|
38
|
+
wotsit.stubs(:thingummy).returns(10)
|
39
|
+
wotsit.stubs(:summat).returns(25)
|
40
|
+
|
41
|
+
you can have...
|
42
|
+
|
43
|
+
wotsit = stub(:thingummy => 5, :summat => 25)
|
44
|
+
|
45
|
+
= 0.1.2
|
46
|
+
|
47
|
+
* Minor tweaks
|
48
|
+
|
49
|
+
= 0.1.1
|
50
|
+
|
51
|
+
* Initial release.
|
data/Rakefile
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake/rdoctask'
|
3
3
|
require 'rake/gempackagetask'
|
4
|
+
require 'rake/contrib/sshpublisher'
|
4
5
|
|
5
6
|
desc "Default task is currently to run all tests"
|
6
7
|
task :default => :test_all
|
@@ -13,9 +14,32 @@ end
|
|
13
14
|
|
14
15
|
desc 'Generate RDoc'
|
15
16
|
Rake::RDocTask.new do |task|
|
17
|
+
task.main = 'README'
|
18
|
+
task.title = 'Mocha'
|
16
19
|
task.rdoc_dir = 'doc'
|
17
|
-
task.options <<
|
18
|
-
task.rdoc_files.include('README', 'lib/**/*.rb')
|
20
|
+
task.options << "--line-numbers" << "--inline-source"
|
21
|
+
task.rdoc_files.include('README', 'RELEASE', 'agiledox.txt', 'lib/**/*.rb')
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "Upload RDoc to RubyForge"
|
25
|
+
task :publish_rdoc => [:rdoc] do
|
26
|
+
Rake::SshDirPublisher.new("jamesmead@rubyforge.org", "/var/www/gforge-projects/mocha", "doc").upload
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "Generate agiledox-like documentation for tests"
|
30
|
+
file 'agiledox.txt' do
|
31
|
+
File.open('agiledox.txt', 'w') do |output|
|
32
|
+
tests = FileList['test/**/*_test.rb']
|
33
|
+
tests.each do |file|
|
34
|
+
m = %r".*/([^/].*)_test.rb".match(file)
|
35
|
+
output << m[1]+" should:\n"
|
36
|
+
test_definitions = File::readlines(file).select {|line| line =~ /.*def test.*/}
|
37
|
+
test_definitions.sort.each do |definition|
|
38
|
+
m = %r"test_(should_)?(.*)".match(definition)
|
39
|
+
output << " - "+m[2].gsub(/_/," ") << "\n"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
19
43
|
end
|
20
44
|
|
21
45
|
Gem::manage_gems
|
@@ -23,7 +47,7 @@ Gem::manage_gems
|
|
23
47
|
specification = Gem::Specification.new do |s|
|
24
48
|
s.name = "mocha"
|
25
49
|
s.summary = "Mocking and stubbing library"
|
26
|
-
s.version = "0.
|
50
|
+
s.version = "0.2.0"
|
27
51
|
s.author = 'James Mead'
|
28
52
|
s.description = <<-EOF
|
29
53
|
Mocking and stubbing library with JMock/SchMock syntax, which allows mocking and stubbing of methods on real (non-mock) classes.
|
data/TODO
CHANGED
@@ -1,20 +1,15 @@
|
|
1
|
-
-
|
1
|
+
- make verify method private (makes this unnecessary - fail if attempt to verify stub)
|
2
|
+
- auto-verify for stubs?
|
3
|
+
- allow hash parameter for stubs and expects methods particularly for stubba
|
2
4
|
- write rdoc for most important methods/classes e.g. expectation
|
3
|
-
-
|
4
|
-
- include functionality into test case using module include for more flexibility - instead of re-opening test/unit/test_case
|
5
|
-
- improve implementation of test case setup/teardown
|
6
|
-
- experienced problem when including a module with setup method into a TestCase derived class (something like nil.unstub_all in teardown)
|
5
|
+
- remove mocha/stubba from call stack when assertion error raised
|
7
6
|
- test for setting expectations on class methods (and instance methods?) from within TestCase#setup
|
8
|
-
- test for verifying expectations from within TestCase#teardown
|
9
7
|
- use Object#inspect(:mocha) instead of Object#mocha_inspect?
|
10
8
|
- allow stubbing of private/protected methods?
|
11
9
|
- should all instances share expectations for any_instance or should each instance have their own - in which case how do we provide access to the instances
|
12
|
-
- check if mocking 'new' method is still possible
|
13
10
|
- detect existing or added definition of mocha methods e.g. expects and alias to __expects?
|
14
|
-
-
|
15
|
-
- auto-verify? default to on, allow switch off?
|
11
|
+
- allow switch off of auto-verify?
|
16
12
|
- fail if verify called with no expectations? set expectation - expects(:blah).never to ensure method not called
|
17
|
-
- fail if attempt to verify stub??
|
18
13
|
- maybe use blank_slate as mocha parent class to allow mocking of standard object methods?
|
19
14
|
- more jmock style stuff - e.g. return values on consecutive calls, labels/required order, more sophisticated param matching?
|
20
15
|
- stubs should only return a fixed value - no blocks allowed for return values and no parameter expectations allowed?
|
data/lib/auto_mocha.rb
CHANGED
data/lib/mocha.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'mocha/mock'
|
2
|
+
|
3
|
+
module AutoVerify
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.add_teardown_method(:teardown_mocks)
|
7
|
+
end
|
8
|
+
|
9
|
+
def mocks
|
10
|
+
@mocks ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
def reset_mocks
|
14
|
+
@mocks = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def mock(expectations = {})
|
18
|
+
mock = Mocha::Mock.new
|
19
|
+
expectations.each do |method, result|
|
20
|
+
mock.expects(method).returns(result)
|
21
|
+
end
|
22
|
+
mocks << mock
|
23
|
+
mock
|
24
|
+
end
|
25
|
+
|
26
|
+
def stub(expectations = {})
|
27
|
+
mock = Mocha::Mock.new
|
28
|
+
expectations.each do |method, result|
|
29
|
+
mock.stubs(method).returns(result)
|
30
|
+
end
|
31
|
+
mocks << mock
|
32
|
+
mock
|
33
|
+
end
|
34
|
+
|
35
|
+
def teardown_mocks
|
36
|
+
mocks.each { |mock| mock.verify }
|
37
|
+
reset_mocks
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module MultipleSetupAndTeardown
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
|
5
|
+
base.class_eval do
|
6
|
+
|
7
|
+
def self.method_added(symbol)
|
8
|
+
# disable until later
|
9
|
+
end
|
10
|
+
|
11
|
+
if method_defined?(:setup) then
|
12
|
+
alias_method :setup_original, :setup
|
13
|
+
define_method(:setup_new) do
|
14
|
+
begin
|
15
|
+
setup_original
|
16
|
+
ensure
|
17
|
+
setup_mocha
|
18
|
+
end
|
19
|
+
end
|
20
|
+
else
|
21
|
+
define_method(:setup_new) do
|
22
|
+
setup_mocha
|
23
|
+
end
|
24
|
+
end
|
25
|
+
alias_method :setup, :setup_new
|
26
|
+
|
27
|
+
if method_defined?(:teardown) then
|
28
|
+
alias_method :teardown_original, :teardown
|
29
|
+
define_method(:teardown_new) do
|
30
|
+
begin
|
31
|
+
teardown_mocha
|
32
|
+
ensure
|
33
|
+
teardown_original
|
34
|
+
end
|
35
|
+
end
|
36
|
+
else
|
37
|
+
define_method(:teardown_new) do
|
38
|
+
teardown_mocha
|
39
|
+
end
|
40
|
+
end
|
41
|
+
alias_method :teardown, :teardown_new
|
42
|
+
|
43
|
+
def self.method_added(method)
|
44
|
+
case method
|
45
|
+
when :setup
|
46
|
+
unless method_defined?(:setup_added)
|
47
|
+
alias_method :setup_added, :setup
|
48
|
+
define_method(:setup) do
|
49
|
+
begin
|
50
|
+
setup_new
|
51
|
+
ensure
|
52
|
+
setup_added
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
when :teardown
|
57
|
+
unless method_defined?(:teardown_added)
|
58
|
+
alias_method :teardown_added, :teardown
|
59
|
+
define_method(:teardown) do
|
60
|
+
begin
|
61
|
+
teardown_added
|
62
|
+
ensure
|
63
|
+
teardown_new
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class << self
|
71
|
+
|
72
|
+
def setup_methods
|
73
|
+
@setup_methods ||= []
|
74
|
+
end
|
75
|
+
|
76
|
+
def teardown_methods
|
77
|
+
@teardown_methods ||= []
|
78
|
+
end
|
79
|
+
|
80
|
+
def add_setup_method(symbol)
|
81
|
+
setup_methods << symbol
|
82
|
+
end
|
83
|
+
|
84
|
+
def add_teardown_method(symbol)
|
85
|
+
teardown_methods << symbol
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def inherited_with_setup_and_teardown_methods(child)
|
91
|
+
inherited_without_setup_and_teardown_methods(child) if respond_to?(:inherited_without_setup_and_teardown_methods, true)
|
92
|
+
child.instance_variable_set('@setup_methods', setup_methods.dup)
|
93
|
+
child.instance_variable_set('@teardown_methods', teardown_methods.dup)
|
94
|
+
end
|
95
|
+
|
96
|
+
if respond_to?(:inherited, true)
|
97
|
+
alias_method :inherited_without_setup_and_teardown_methods, :inherited
|
98
|
+
end
|
99
|
+
alias_method :inherited, :inherited_with_setup_and_teardown_methods
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
def setup_mocha
|
104
|
+
self.class.class_eval { setup_methods }.each { |symbol| send(symbol) }
|
105
|
+
end
|
106
|
+
|
107
|
+
def teardown_mocha
|
108
|
+
self.class.class_eval { teardown_methods }.reverse.each { |symbol| send(symbol) }
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
data/lib/stubba.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'stubba/central'
|
2
|
+
|
3
|
+
module SetupAndTeardown
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.add_setup_method(:setup_stubs)
|
7
|
+
base.add_teardown_method(:teardown_stubs)
|
8
|
+
end
|
9
|
+
|
10
|
+
def setup_stubs
|
11
|
+
$stubba = Stubba::Central.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def teardown_stubs
|
15
|
+
$stubba.unstub_all if $stubba
|
16
|
+
$stubba = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module ActiveRecordTestCase
|
2
|
+
|
3
|
+
def setup_with_fixtures
|
4
|
+
methods_called << :setup_with_fixtures
|
5
|
+
end
|
6
|
+
|
7
|
+
alias_method :setup, :setup_with_fixtures
|
8
|
+
|
9
|
+
def teardown_with_fixtures
|
10
|
+
methods_called << :teardown_with_fixtures
|
11
|
+
end
|
12
|
+
|
13
|
+
alias_method :teardown, :teardown_with_fixtures
|
14
|
+
|
15
|
+
def self.method_added(method)
|
16
|
+
case method.to_s
|
17
|
+
when 'setup'
|
18
|
+
unless method_defined?(:setup_without_fixtures)
|
19
|
+
alias_method :setup_without_fixtures, :setup
|
20
|
+
define_method(:setup) do
|
21
|
+
setup_with_fixtures
|
22
|
+
setup_without_fixtures
|
23
|
+
end
|
24
|
+
end
|
25
|
+
when 'teardown'
|
26
|
+
unless method_defined?(:teardown_without_fixtures)
|
27
|
+
alias_method :teardown_without_fixtures, :teardown
|
28
|
+
define_method(:teardown) do
|
29
|
+
teardown_without_fixtures
|
30
|
+
teardown_with_fixtures
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|