mocha 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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 three parts:
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 Mocha with the following command.
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
- require 'rubygems'
48
- require 'mocha'
49
- require 'test/unit'
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 = Mock.new
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 = Mock.new(:accepted? => false)
156
- accepted_comment = Mock.new(:accepted? => true)
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 << '--title Mocha --main README --line-numbers --inline-source'
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.1.2"
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
- - check examples in readme
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
- - mock() method on test case to hide implementation detail of Mocha.new
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
- - think more about different behaviour for expects/stubs
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?
@@ -1 +1,2 @@
1
+ require 'mocha'
1
2
  require 'auto_mocha/auto_mock'
@@ -1 +1,6 @@
1
- require 'mocha/mock'
1
+ require 'smart_test_case'
2
+ require 'mocha/auto_verify'
3
+
4
+ class Test::Unit::TestCase
5
+ include AutoVerify unless ancestors.include?(AutoVerify)
6
+ end
@@ -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,5 @@
1
+ require 'smart_test_case/multiple_setup_and_teardown'
2
+
3
+ class Test::Unit::TestCase
4
+ include MultipleSetupAndTeardown unless ancestors.include?(MultipleSetupAndTeardown)
5
+ end
@@ -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
@@ -1,2 +1,7 @@
1
- require 'stubba/test_case'
2
1
  require 'stubba/object'
2
+ require 'smart_test_case'
3
+ require 'stubba/setup_and_teardown'
4
+
5
+ class Test::Unit::TestCase
6
+ include SetupAndTeardown unless ancestors.include?(SetupAndTeardown)
7
+ end
@@ -1,6 +1,6 @@
1
1
  module Stubba
2
2
 
3
- class Stubba
3
+ class Central
4
4
 
5
5
  attr_accessor :stubba_methods
6
6
 
@@ -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