mocha 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +6 -2
- data/RELEASE +11 -0
- data/Rakefile +1 -1
- data/TODO +1 -3
- data/lib/mocha.rb +1 -0
- data/lib/mocha/auto_verify.rb +18 -13
- data/lib/mocha/expectation.rb +18 -3
- data/lib/mocha/mock.rb +2 -19
- data/lib/mocha/mock_methods.rb +16 -13
- data/lib/shared/backtracefilter.rb +46 -0
- data/lib/smart_test_case/multiple_setup_and_teardown.rb +9 -1
- data/lib/stubba.rb +1 -0
- data/lib/stubba/any_instance_method.rb +9 -5
- data/lib/stubba/central.rb +8 -0
- data/lib/stubba/class_method.rb +15 -11
- data/lib/stubba/instance_method.rb +1 -1
- data/lib/stubba/object.rb +4 -4
- data/lib/stubba/setup_and_teardown.rb +8 -2
- data/test/all_tests.rb +4 -0
- data/test/execution_point.rb +34 -0
- data/test/mocha/auto_verify_test.rb +103 -3
- data/test/mocha/expectation_test.rb +64 -1
- data/test/mocha/mock_methods_test.rb +55 -19
- data/test/mocha/mock_test.rb +11 -38
- data/test/mocha_test_result_integration_test.rb +106 -0
- data/test/smart_test_case/multiple_setup_and_teardown_test.rb +132 -31
- data/test/stubba/any_instance_method_test.rb +14 -2
- data/test/stubba/central_test.rb +62 -2
- data/test/stubba/class_method_test.rb +19 -1
- data/test/stubba/object_test.rb +41 -8
- data/test/stubba/setup_and_teardown_test.rb +60 -2
- data/test/stubba_acceptance_test.rb +0 -5
- data/test/stubba_test_result_integration_test.rb +86 -0
- data/test/test_helper.rb +2 -2
- metadata +6 -2
data/README
CHANGED
@@ -20,6 +20,10 @@ Mocha and Stubba have been created by amalgamating a number of techniques develo
|
|
20
20
|
You can download Mocha from here[http://rubyforge.org/projects/mocha] or install it with the following command.
|
21
21
|
|
22
22
|
$ gem install mocha
|
23
|
+
|
24
|
+
== Ruby on Rails plugin
|
25
|
+
|
26
|
+
$ script/plugin install svn://rubyforge.org/var/svn/mocha/trunk
|
23
27
|
|
24
28
|
== License
|
25
29
|
|
@@ -45,9 +49,9 @@ See MochaAcceptanceTest, StubbaAcceptanceTest, AutoMochaAcceptanceTest and unit
|
|
45
49
|
|
46
50
|
end
|
47
51
|
|
52
|
+
require 'test/unit'
|
48
53
|
require 'rubygems'
|
49
54
|
require 'mocha'
|
50
|
-
require 'test/unit'
|
51
55
|
|
52
56
|
class EnterpriseTest < Test::Unit::TestCase
|
53
57
|
|
@@ -96,9 +100,9 @@ See MochaAcceptanceTest, StubbaAcceptanceTest, AutoMochaAcceptanceTest and unit
|
|
96
100
|
|
97
101
|
end
|
98
102
|
|
103
|
+
require 'test/unit'
|
99
104
|
require 'rubygems'
|
100
105
|
require 'stubba'
|
101
|
-
require 'test/unit'
|
102
106
|
|
103
107
|
class OrderTest < Test::Unit::TestCase
|
104
108
|
|
data/RELEASE
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
= 0.3.0
|
2
|
+
|
3
|
+
* Rails plugin.
|
4
|
+
* Auto-verify for expectations on concrete classes.
|
5
|
+
* Include each expectation verification in the test result assertion count.
|
6
|
+
* Filter out noise from assertion backtraces.
|
7
|
+
* Point assertion backtrace to line where failing expectation was created.
|
8
|
+
* New yields method for expectations.
|
9
|
+
* Create stubs which stub all method calls.
|
10
|
+
* Mocks now respond_to? expected methods.
|
11
|
+
|
1
12
|
= 0.2.1
|
2
13
|
|
3
14
|
* Rename MochaAcceptanceTest::Rover#move method to avoid conflict with Rake (in Ruby 1.8.4 only?)
|
data/Rakefile
CHANGED
@@ -47,7 +47,7 @@ Gem::manage_gems
|
|
47
47
|
specification = Gem::Specification.new do |s|
|
48
48
|
s.name = "mocha"
|
49
49
|
s.summary = "Mocking and stubbing library"
|
50
|
-
s.version = "0.
|
50
|
+
s.version = "0.3.0"
|
51
51
|
s.author = 'James Mead'
|
52
52
|
s.description = <<-EOF
|
53
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,15 +1,13 @@
|
|
1
|
+
- think about behaviour when more than one expectation/stubbed method match
|
1
2
|
- make verify method private (makes this unnecessary - fail if attempt to verify stub)
|
2
|
-
- auto-verify for stubs?
|
3
3
|
- allow hash parameter for stubs and expects methods particularly for stubba
|
4
4
|
- write rdoc for most important methods/classes e.g. expectation
|
5
|
-
- remove mocha/stubba from call stack when assertion error raised
|
6
5
|
- test for setting expectations on class methods (and instance methods?) from within TestCase#setup
|
7
6
|
- use Object#inspect(:mocha) instead of Object#mocha_inspect?
|
8
7
|
- allow stubbing of private/protected methods?
|
9
8
|
- 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
|
10
9
|
- detect existing or added definition of mocha methods e.g. expects and alias to __expects?
|
11
10
|
- allow switch off of auto-verify?
|
12
|
-
- fail if verify called with no expectations? set expectation - expects(:blah).never to ensure method not called
|
13
11
|
- maybe use blank_slate as mocha parent class to allow mocking of standard object methods?
|
14
12
|
- more jmock style stuff - e.g. return values on consecutive calls, labels/required order, more sophisticated param matching?
|
15
13
|
- stubs should only return a fixed value - no blocks allowed for return values and no parameter expectations allowed?
|
data/lib/mocha.rb
CHANGED
data/lib/mocha/auto_verify.rb
CHANGED
@@ -15,27 +15,32 @@ module AutoVerify
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def mock(expectations = {})
|
18
|
-
|
19
|
-
expectations.each do |method, result|
|
20
|
-
mock.expects(method).returns(result)
|
21
|
-
end
|
22
|
-
mocks << mock
|
23
|
-
mock
|
18
|
+
build_mock_with_expectations(:expects, expectations)
|
24
19
|
end
|
25
20
|
|
26
21
|
def stub(expectations = {})
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
mock
|
22
|
+
build_mock_with_expectations(:stubs, expectations)
|
23
|
+
end
|
24
|
+
|
25
|
+
def stub_everything(expectations = {})
|
26
|
+
build_mock_with_expectations(:stub_everything, expectations)
|
33
27
|
end
|
34
28
|
|
35
29
|
def teardown_mocks
|
36
|
-
mocks.each { |mock| mock.verify }
|
30
|
+
mocks.each { |mock| mock.verify { add_assertion } }
|
37
31
|
reset_mocks
|
38
32
|
end
|
39
33
|
|
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)
|
40
|
+
end
|
41
|
+
mocks << mock
|
42
|
+
mock
|
43
|
+
end
|
44
|
+
|
40
45
|
end
|
41
46
|
|
data/lib/mocha/expectation.rb
CHANGED
@@ -15,13 +15,18 @@ module Mocha
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
attr_reader :method_name
|
18
|
+
attr_reader :method_name, :backtrace
|
19
19
|
|
20
|
-
def initialize(method_name)
|
20
|
+
def initialize(method_name, backtrace = nil)
|
21
21
|
@method_name = method_name
|
22
22
|
@count = 1
|
23
23
|
@parameters, @parameter_block = AlwaysEqual.new, nil
|
24
24
|
@invoked, @return_value = 0, nil
|
25
|
+
@backtrace = backtrace || caller
|
26
|
+
end
|
27
|
+
|
28
|
+
def yield?
|
29
|
+
@yield
|
25
30
|
end
|
26
31
|
|
27
32
|
def match?(method_name, *arguments)
|
@@ -57,6 +62,12 @@ module Mocha
|
|
57
62
|
self
|
58
63
|
end
|
59
64
|
|
65
|
+
def yields(*parameters)
|
66
|
+
@yield = true
|
67
|
+
@parameters_to_yield = parameters
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
60
71
|
def returns(value)
|
61
72
|
@return_value = value
|
62
73
|
self
|
@@ -69,12 +80,16 @@ module Mocha
|
|
69
80
|
|
70
81
|
def invoke
|
71
82
|
@invoked += 1
|
83
|
+
yield(*@parameters_to_yield) if yield? and block_given?
|
72
84
|
@return_value.is_a?(Proc) ? @return_value.call : @return_value
|
73
85
|
end
|
74
86
|
|
75
87
|
def verify
|
88
|
+
yield(self) if block_given?
|
76
89
|
unless (@count === @invoked) then
|
77
|
-
|
90
|
+
failure = Test::Unit::AssertionFailedError.new("#{message}: expected calls: #{@count}, actual calls: #{@invoked}")
|
91
|
+
failure.set_backtrace(backtrace)
|
92
|
+
raise failure
|
78
93
|
end
|
79
94
|
end
|
80
95
|
|
data/lib/mocha/mock.rb
CHANGED
@@ -1,30 +1,13 @@
|
|
1
1
|
require 'mocha/mock_methods'
|
2
|
-
require 'test/unit/assertions'
|
3
2
|
|
4
3
|
module Mocha
|
5
4
|
class Mock
|
6
5
|
|
7
6
|
include MockMethods
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
def initialize(*arguments)
|
12
|
-
@mocked = arguments.shift unless arguments.first.is_a?(Hash)
|
13
|
-
@mocked ||= always_responds
|
14
|
-
expectations = arguments.shift || {}
|
15
|
-
expectations.each do |method_name, result|
|
16
|
-
expects(method_name).returns(result)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def expects(symbol)
|
21
|
-
raise Test::Unit::AssertionFailedError, "Cannot replace #{symbol} as #{@mocked} does not respond to it." unless @mocked.respond_to?(symbol)
|
22
|
-
super
|
8
|
+
def initialize(stub_everything = false)
|
9
|
+
@stub_everything = stub_everything
|
23
10
|
end
|
24
11
|
|
25
|
-
def always_responds
|
26
|
-
Class.new { def respond_to?(symbol); true; end }.new
|
27
|
-
end
|
28
|
-
|
29
12
|
end
|
30
13
|
end
|
data/lib/mocha/mock_methods.rb
CHANGED
@@ -2,25 +2,29 @@ require 'mocha/expectation'
|
|
2
2
|
|
3
3
|
module Mocha
|
4
4
|
module MockMethods
|
5
|
+
|
6
|
+
attr_reader :stub_everything
|
5
7
|
|
6
8
|
def expectations
|
7
9
|
@expectations ||= []
|
8
10
|
end
|
9
11
|
|
10
|
-
def expects(symbol)
|
11
|
-
expectations << Expectation.new(symbol)
|
12
|
+
def expects(symbol, backtrace = nil)
|
13
|
+
expectations << Expectation.new(symbol, backtrace)
|
12
14
|
expectations.last
|
13
15
|
end
|
14
16
|
|
15
|
-
def stubs(symbol)
|
16
|
-
expectations << Stub.new(symbol)
|
17
|
+
def stubs(symbol, backtrace = nil)
|
18
|
+
expectations << Stub.new(symbol, backtrace)
|
17
19
|
expectations.last
|
18
20
|
end
|
19
|
-
|
21
|
+
|
20
22
|
def method_missing(symbol, *arguments, &block)
|
21
23
|
matching_expectation = matching_expectation(symbol, *arguments)
|
22
24
|
if matching_expectation then
|
23
|
-
matching_expectation.invoke
|
25
|
+
matching_expectation.invoke(&block)
|
26
|
+
elsif stub_everything then
|
27
|
+
return
|
24
28
|
else
|
25
29
|
begin
|
26
30
|
super_method_missing(symbol, *arguments, &block)
|
@@ -29,6 +33,10 @@ module Mocha
|
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
36
|
+
|
37
|
+
def respond_to?(symbol)
|
38
|
+
expectations.any? { |expectation| expectation.method_name == symbol }
|
39
|
+
end
|
32
40
|
|
33
41
|
def super_method_missing(symbol, *arguments, &block)
|
34
42
|
raise NoMethodError
|
@@ -42,13 +50,8 @@ module Mocha
|
|
42
50
|
expectations.detect { |expectation| expectation.match?(symbol, *arguments) }
|
43
51
|
end
|
44
52
|
|
45
|
-
def
|
46
|
-
expectations.
|
47
|
-
end
|
48
|
-
|
49
|
-
def verify(*method_names)
|
50
|
-
for_verification = method_names.empty? ? expectations : expectations_matching(method_names)
|
51
|
-
for_verification.each { |expectation| expectation.verify }
|
53
|
+
def verify(&block)
|
54
|
+
expectations.each { |expectation| expectation.verify(&block) }
|
52
55
|
end
|
53
56
|
|
54
57
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Test
|
2
|
+
module Unit
|
3
|
+
module Util
|
4
|
+
module BacktraceFilter
|
5
|
+
|
6
|
+
# quick rip-off of Test::Unit code - there must be a better way of doing this!
|
7
|
+
|
8
|
+
MOCHA_FILE_SEPARATORS = %r{[\\/:]}
|
9
|
+
MOCHA_PREFIX = __FILE__.split(MOCHA_FILE_SEPARATORS)[0..-3]
|
10
|
+
MOCHA_RB_FILE = /\.rb\Z/
|
11
|
+
|
12
|
+
alias_method :__filter_backtrace__, :filter_backtrace
|
13
|
+
|
14
|
+
def filter_backtrace(backtrace, prefix=nil)
|
15
|
+
backtrace = __filter_backtrace__(backtrace, prefix)
|
16
|
+
return ["No backtrace"] unless(backtrace)
|
17
|
+
split_p = if(prefix)
|
18
|
+
prefix.split(MOCHA_FILE_SEPARATORS)
|
19
|
+
else
|
20
|
+
MOCHA_PREFIX
|
21
|
+
end
|
22
|
+
match = proc do |e|
|
23
|
+
split_e = e.split(MOCHA_FILE_SEPARATORS)[0, split_p.size]
|
24
|
+
next false unless(split_e[0..-2] == split_p[0..-2])
|
25
|
+
split_e[-1].sub(MOCHA_RB_FILE, '') == split_p[-1]
|
26
|
+
end
|
27
|
+
return backtrace unless(backtrace.detect(&match))
|
28
|
+
found_prefix = false
|
29
|
+
new_backtrace = backtrace.reverse.reject do |e|
|
30
|
+
if(match[e])
|
31
|
+
found_prefix = true
|
32
|
+
true
|
33
|
+
elsif(found_prefix)
|
34
|
+
false
|
35
|
+
else
|
36
|
+
true
|
37
|
+
end
|
38
|
+
end.reverse
|
39
|
+
new_backtrace = (new_backtrace.empty? ? backtrace : new_backtrace)
|
40
|
+
new_backtrace = new_backtrace.reject(&match)
|
41
|
+
new_backtrace.empty? ? backtrace : new_backtrace
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -105,7 +105,15 @@ module MultipleSetupAndTeardown
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def teardown_mocha
|
108
|
-
|
108
|
+
stored_exception = nil
|
109
|
+
self.class.class_eval { teardown_methods }.reverse.each do |symbol|
|
110
|
+
begin
|
111
|
+
send(symbol)
|
112
|
+
rescue Exception => e
|
113
|
+
stored_exception ||= e
|
114
|
+
end
|
115
|
+
end
|
116
|
+
raise stored_exception if stored_exception
|
109
117
|
end
|
110
118
|
|
111
119
|
end
|
data/lib/stubba.rb
CHANGED
@@ -7,23 +7,27 @@ module Stubba
|
|
7
7
|
def unstub
|
8
8
|
remove_new_method
|
9
9
|
restore_original_method
|
10
|
-
|
10
|
+
stubbee.any_instance.reset_mocha
|
11
|
+
end
|
12
|
+
|
13
|
+
def mock
|
14
|
+
stubbee.any_instance.mocha
|
11
15
|
end
|
12
16
|
|
13
17
|
def hide_original_method
|
14
|
-
|
18
|
+
stubbee.class_eval "alias_method :#{hidden_method}, :#{method}" if stubbee.method_defined?(method)
|
15
19
|
end
|
16
20
|
|
17
21
|
def define_new_method
|
18
|
-
|
22
|
+
stubbee.class_eval "def #{method}(*args, &block); self.class.any_instance.mocha.method_missing(:#{method}, *args, &block); end"
|
19
23
|
end
|
20
24
|
|
21
25
|
def remove_new_method
|
22
|
-
|
26
|
+
stubbee.class_eval "remove_method :#{method}"
|
23
27
|
end
|
24
28
|
|
25
29
|
def restore_original_method
|
26
|
-
|
30
|
+
stubbee.class_eval "alias_method :#{method}, :#{hidden_method}; remove_method :#{hidden_method}" if stubbee.method_defined?(hidden_method)
|
27
31
|
end
|
28
32
|
|
29
33
|
end
|
data/lib/stubba/central.rb
CHANGED
@@ -14,6 +14,14 @@ module Stubba
|
|
14
14
|
stubba_methods.push method
|
15
15
|
end
|
16
16
|
end
|
17
|
+
|
18
|
+
def verify_all(&block)
|
19
|
+
unique_mocks.each { |mock| mock.verify(&block) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def unique_mocks
|
23
|
+
stubba_methods.collect { |method| method.mock }.uniq
|
24
|
+
end
|
17
25
|
|
18
26
|
def unstub_all
|
19
27
|
while stubba_methods.size > 0
|
data/lib/stubba/class_method.rb
CHANGED
@@ -4,10 +4,10 @@ module Stubba
|
|
4
4
|
|
5
5
|
class ClassMethod
|
6
6
|
|
7
|
-
attr_reader :
|
7
|
+
attr_reader :stubbee, :method
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
@
|
9
|
+
def initialize(stubbee, method)
|
10
|
+
@stubbee, @method = stubbee, method
|
11
11
|
end
|
12
12
|
|
13
13
|
def stub
|
@@ -18,23 +18,27 @@ module Stubba
|
|
18
18
|
def unstub
|
19
19
|
remove_new_method
|
20
20
|
restore_original_method
|
21
|
-
|
21
|
+
stubbee.reset_mocha
|
22
|
+
end
|
23
|
+
|
24
|
+
def mock
|
25
|
+
stubbee.mocha
|
22
26
|
end
|
23
27
|
|
24
28
|
def hide_original_method
|
25
|
-
|
29
|
+
stubbee.metaclass.class_eval "alias_method :#{hidden_method}, :#{method}" if stubbee.metaclass.method_defined?(method)
|
26
30
|
end
|
27
31
|
|
28
32
|
def define_new_method
|
29
|
-
|
33
|
+
stubbee.metaclass.class_eval "def #{method}(*args, &block); mocha.method_missing(:#{method}, *args, &block); end"
|
30
34
|
end
|
31
35
|
|
32
36
|
def remove_new_method
|
33
|
-
|
37
|
+
stubbee.metaclass.class_eval "remove_method :#{method}"
|
34
38
|
end
|
35
39
|
|
36
40
|
def restore_original_method
|
37
|
-
|
41
|
+
stubbee.metaclass.class_eval "alias_method :#{method}, :#{hidden_method}; remove_method :#{hidden_method}" if stubbee.metaclass.method_defined?(hidden_method)
|
38
42
|
end
|
39
43
|
|
40
44
|
def hidden_method
|
@@ -42,18 +46,18 @@ module Stubba
|
|
42
46
|
end
|
43
47
|
|
44
48
|
def cannot_replace_method_error
|
45
|
-
Test::Unit::AssertionFailedError.new("Cannot replace #{method} because it is not defined in #{
|
49
|
+
Test::Unit::AssertionFailedError.new("Cannot replace #{method} because it is not defined in #{stubbee}.")
|
46
50
|
end
|
47
51
|
|
48
52
|
def eql?(other)
|
49
53
|
return false unless (other.class == self.class)
|
50
|
-
(
|
54
|
+
(stubbee == other.stubbee) and (method == other.method)
|
51
55
|
end
|
52
56
|
|
53
57
|
alias_method :==, :eql?
|
54
58
|
|
55
59
|
def to_s
|
56
|
-
"#{
|
60
|
+
"#{stubbee}.#{method}"
|
57
61
|
end
|
58
62
|
|
59
63
|
end
|