mocha 0.5.6 → 3.0.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.
Files changed (192) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/.github/FUNDING.yml +1 -0
  4. data/.rubocop.yml +92 -0
  5. data/.rubocop_todo.yml +39 -0
  6. data/.yardopts +25 -0
  7. data/CONTRIBUTING.md +7 -0
  8. data/COPYING.md +3 -0
  9. data/Gemfile +17 -0
  10. data/{MIT-LICENSE → MIT-LICENSE.md} +2 -2
  11. data/README.md +361 -0
  12. data/RELEASE.md +1235 -0
  13. data/Rakefile +165 -123
  14. data/gemfiles/Gemfile.minitest.latest +8 -0
  15. data/gemfiles/Gemfile.rubocop +9 -0
  16. data/gemfiles/Gemfile.test-unit.latest +8 -0
  17. data/lib/mocha/any_instance_method.rb +12 -26
  18. data/lib/mocha/any_instance_receiver.rb +20 -0
  19. data/lib/mocha/api.rb +213 -0
  20. data/lib/mocha/argument_iterator.rb +17 -0
  21. data/lib/mocha/backtrace_filter.rb +15 -0
  22. data/lib/mocha/block_matchers.rb +33 -0
  23. data/lib/mocha/cardinality.rb +110 -0
  24. data/lib/mocha/central.rb +33 -22
  25. data/lib/mocha/change_state_side_effect.rb +17 -0
  26. data/lib/mocha/class_methods.rb +67 -0
  27. data/lib/mocha/configuration.rb +338 -0
  28. data/lib/mocha/default_name.rb +15 -0
  29. data/lib/mocha/default_receiver.rb +13 -0
  30. data/lib/mocha/deprecation.rb +19 -14
  31. data/lib/mocha/detection/minitest.rb +25 -0
  32. data/lib/mocha/detection/test_unit.rb +30 -0
  33. data/lib/mocha/error_with_filtered_backtrace.rb +15 -0
  34. data/lib/mocha/exception_raiser.rb +11 -10
  35. data/lib/mocha/expectation.rb +553 -168
  36. data/lib/mocha/expectation_error.rb +9 -14
  37. data/lib/mocha/expectation_error_factory.rb +37 -0
  38. data/lib/mocha/expectation_list.rb +30 -14
  39. data/lib/mocha/hooks.rb +55 -0
  40. data/lib/mocha/ignoring_warning.rb +20 -0
  41. data/lib/mocha/impersonating_any_instance_name.rb +13 -0
  42. data/lib/mocha/impersonating_name.rb +13 -0
  43. data/lib/mocha/in_state_ordering_constraint.rb +17 -0
  44. data/lib/mocha/inspect.rb +56 -22
  45. data/lib/mocha/instance_method.rb +17 -4
  46. data/lib/mocha/integration/assertion_counter.rb +15 -0
  47. data/lib/mocha/integration/minitest/adapter.rb +71 -0
  48. data/lib/mocha/integration/minitest.rb +29 -0
  49. data/lib/mocha/integration/monkey_patcher.rb +26 -0
  50. data/lib/mocha/integration/test_unit/adapter.rb +61 -0
  51. data/lib/mocha/integration/test_unit.rb +29 -0
  52. data/lib/mocha/integration.rb +5 -0
  53. data/lib/mocha/invocation.rb +76 -0
  54. data/lib/mocha/logger.rb +13 -0
  55. data/lib/mocha/macos_version.rb +7 -0
  56. data/lib/mocha/method_matcher.rb +8 -10
  57. data/lib/mocha/minitest.rb +7 -0
  58. data/lib/mocha/mock.rb +333 -108
  59. data/lib/mocha/mockery.rb +199 -0
  60. data/lib/mocha/name.rb +13 -0
  61. data/lib/mocha/not_initialized_error.rb +9 -0
  62. data/lib/mocha/object_methods.rb +183 -0
  63. data/lib/mocha/object_receiver.rb +20 -0
  64. data/lib/mocha/parameter_matchers/all_of.rb +38 -28
  65. data/lib/mocha/parameter_matchers/any_of.rb +44 -33
  66. data/lib/mocha/parameter_matchers/any_parameters.rb +33 -26
  67. data/lib/mocha/parameter_matchers/anything.rb +31 -22
  68. data/lib/mocha/parameter_matchers/base_methods.rb +64 -0
  69. data/lib/mocha/parameter_matchers/equals.rb +36 -25
  70. data/lib/mocha/parameter_matchers/equivalent_uri.rb +65 -0
  71. data/lib/mocha/parameter_matchers/has_entries.rb +48 -29
  72. data/lib/mocha/parameter_matchers/has_entry.rb +90 -42
  73. data/lib/mocha/parameter_matchers/has_key.rb +39 -26
  74. data/lib/mocha/parameter_matchers/has_keys.rb +59 -0
  75. data/lib/mocha/parameter_matchers/has_value.rb +39 -26
  76. data/lib/mocha/parameter_matchers/includes.rb +88 -23
  77. data/lib/mocha/parameter_matchers/instance_methods.rb +28 -0
  78. data/lib/mocha/parameter_matchers/instance_of.rb +37 -26
  79. data/lib/mocha/parameter_matchers/is_a.rb +38 -26
  80. data/lib/mocha/parameter_matchers/kind_of.rb +39 -26
  81. data/lib/mocha/parameter_matchers/not.rb +37 -26
  82. data/lib/mocha/parameter_matchers/optionally.rb +52 -17
  83. data/lib/mocha/parameter_matchers/positional_or_keyword_hash.rb +91 -0
  84. data/lib/mocha/parameter_matchers/regexp_matches.rb +37 -25
  85. data/lib/mocha/parameter_matchers/responds_with.rb +82 -0
  86. data/lib/mocha/parameter_matchers/yaml_equivalent.rb +55 -0
  87. data/lib/mocha/parameter_matchers.rb +12 -5
  88. data/lib/mocha/parameters_matcher.rb +28 -19
  89. data/lib/mocha/raised_exception.rb +13 -0
  90. data/lib/mocha/return_values.rb +13 -18
  91. data/lib/mocha/ruby_version.rb +7 -0
  92. data/lib/mocha/sequence.rb +23 -17
  93. data/lib/mocha/single_return_value.rb +8 -18
  94. data/lib/mocha/state_machine.rb +95 -0
  95. data/lib/mocha/stubbed_method.rb +96 -0
  96. data/lib/mocha/stubbing_error.rb +10 -0
  97. data/lib/mocha/test_unit.rb +7 -0
  98. data/lib/mocha/thrower.rb +15 -0
  99. data/lib/mocha/thrown_object.rb +14 -0
  100. data/lib/mocha/version.rb +5 -0
  101. data/lib/mocha/yield_parameters.rb +12 -20
  102. data/lib/mocha.rb +19 -17
  103. data/mise.toml +2 -0
  104. data/mocha.gemspec +40 -0
  105. metadata +130 -145
  106. data/COPYING +0 -3
  107. data/README +0 -35
  108. data/RELEASE +0 -188
  109. data/examples/misc.rb +0 -44
  110. data/examples/mocha.rb +0 -26
  111. data/examples/stubba.rb +0 -65
  112. data/lib/mocha/auto_verify.rb +0 -118
  113. data/lib/mocha/class_method.rb +0 -66
  114. data/lib/mocha/infinite_range.rb +0 -25
  115. data/lib/mocha/is_a.rb +0 -9
  116. data/lib/mocha/metaclass.rb +0 -7
  117. data/lib/mocha/missing_expectation.rb +0 -17
  118. data/lib/mocha/multiple_yields.rb +0 -20
  119. data/lib/mocha/no_yields.rb +0 -11
  120. data/lib/mocha/object.rb +0 -110
  121. data/lib/mocha/parameter_matchers/base.rb +0 -15
  122. data/lib/mocha/parameter_matchers/object.rb +0 -9
  123. data/lib/mocha/pretty_parameters.rb +0 -28
  124. data/lib/mocha/setup_and_teardown.rb +0 -23
  125. data/lib/mocha/single_yield.rb +0 -18
  126. data/lib/mocha/standalone.rb +0 -32
  127. data/lib/mocha/stub.rb +0 -18
  128. data/lib/mocha/test_case_adapter.rb +0 -49
  129. data/lib/mocha_standalone.rb +0 -2
  130. data/lib/stubba.rb +0 -2
  131. data/test/acceptance/expected_invocation_count_acceptance_test.rb +0 -187
  132. data/test/acceptance/mocha_acceptance_test.rb +0 -98
  133. data/test/acceptance/mock_with_initializer_block_acceptance_test.rb +0 -44
  134. data/test/acceptance/mocked_methods_dispatch_acceptance_test.rb +0 -71
  135. data/test/acceptance/optional_parameters_acceptance_test.rb +0 -63
  136. data/test/acceptance/parameter_matcher_acceptance_test.rb +0 -117
  137. data/test/acceptance/partial_mocks_acceptance_test.rb +0 -40
  138. data/test/acceptance/sequence_acceptance_test.rb +0 -179
  139. data/test/acceptance/standalone_acceptance_test.rb +0 -131
  140. data/test/acceptance/stubba_acceptance_test.rb +0 -102
  141. data/test/active_record_test_case.rb +0 -36
  142. data/test/deprecation_disabler.rb +0 -15
  143. data/test/execution_point.rb +0 -34
  144. data/test/integration/mocha_test_result_integration_test.rb +0 -105
  145. data/test/integration/stubba_integration_test.rb +0 -89
  146. data/test/integration/stubba_test_result_integration_test.rb +0 -85
  147. data/test/method_definer.rb +0 -18
  148. data/test/test_helper.rb +0 -12
  149. data/test/test_runner.rb +0 -31
  150. data/test/unit/any_instance_method_test.rb +0 -126
  151. data/test/unit/array_inspect_test.rb +0 -16
  152. data/test/unit/auto_verify_test.rb +0 -129
  153. data/test/unit/central_test.rb +0 -124
  154. data/test/unit/class_method_test.rb +0 -200
  155. data/test/unit/date_time_inspect_test.rb +0 -21
  156. data/test/unit/expectation_error_test.rb +0 -24
  157. data/test/unit/expectation_list_test.rb +0 -75
  158. data/test/unit/expectation_raiser_test.rb +0 -28
  159. data/test/unit/expectation_test.rb +0 -483
  160. data/test/unit/hash_inspect_test.rb +0 -16
  161. data/test/unit/infinite_range_test.rb +0 -53
  162. data/test/unit/metaclass_test.rb +0 -22
  163. data/test/unit/method_matcher_test.rb +0 -23
  164. data/test/unit/missing_expectation_test.rb +0 -42
  165. data/test/unit/mock_test.rb +0 -323
  166. data/test/unit/multiple_yields_test.rb +0 -18
  167. data/test/unit/no_yield_test.rb +0 -18
  168. data/test/unit/object_inspect_test.rb +0 -37
  169. data/test/unit/object_test.rb +0 -165
  170. data/test/unit/parameter_matchers/all_of_test.rb +0 -26
  171. data/test/unit/parameter_matchers/any_of_test.rb +0 -26
  172. data/test/unit/parameter_matchers/anything_test.rb +0 -21
  173. data/test/unit/parameter_matchers/has_entries_test.rb +0 -30
  174. data/test/unit/parameter_matchers/has_entry_test.rb +0 -40
  175. data/test/unit/parameter_matchers/has_key_test.rb +0 -25
  176. data/test/unit/parameter_matchers/has_value_test.rb +0 -25
  177. data/test/unit/parameter_matchers/includes_test.rb +0 -25
  178. data/test/unit/parameter_matchers/instance_of_test.rb +0 -25
  179. data/test/unit/parameter_matchers/is_a_test.rb +0 -25
  180. data/test/unit/parameter_matchers/kind_of_test.rb +0 -25
  181. data/test/unit/parameter_matchers/not_test.rb +0 -26
  182. data/test/unit/parameter_matchers/regexp_matches_test.rb +0 -25
  183. data/test/unit/parameter_matchers/stub_matcher.rb +0 -23
  184. data/test/unit/parameters_matcher_test.rb +0 -121
  185. data/test/unit/return_values_test.rb +0 -63
  186. data/test/unit/sequence_test.rb +0 -104
  187. data/test/unit/setup_and_teardown_test.rb +0 -76
  188. data/test/unit/single_return_value_test.rb +0 -33
  189. data/test/unit/single_yield_test.rb +0 -18
  190. data/test/unit/string_inspect_test.rb +0 -11
  191. data/test/unit/stub_test.rb +0 -24
  192. data/test/unit/yield_parameters_test.rb +0 -93
data/Rakefile CHANGED
@@ -1,149 +1,191 @@
1
- require 'rubygems'
2
- require 'rake/rdoctask'
3
- require 'rake/gempackagetask'
4
- require 'rake/testtask'
5
- require 'rake/contrib/sshpublisher'
6
-
7
- module Mocha
8
- VERSION = "0.5.6"
1
+ require 'bundler'
2
+ namespace 'rubygems' do
3
+ Bundler::GemHelper.install_tasks
9
4
  end
5
+ require 'bundler/setup'
10
6
 
11
- desc "Run all tests"
12
- task :default => :test_all
7
+ require 'rake/testtask'
8
+ begin
9
+ # Only available with `gemfiles/Gemfile.rubocop`
10
+ require 'rubocop/rake_task'
11
+ rescue LoadError
12
+ warn "Unable to load 'rubocop/rake_task', but continuing anyway" if $DEBUG
13
+ end
13
14
 
14
- task :test_all => [:test_unit, :test_integration, :test_acceptance]
15
+ desc 'Run all linters and tests'
16
+ task 'default' => ['lint', 'test', 'test:performance']
15
17
 
16
- desc "Run unit tests"
17
- Rake::TestTask.new(:test_unit) do |t|
18
- t.libs << 'test'
19
- t.test_files = FileList['test/unit/**/*_test.rb']
20
- t.verbose = true
21
- t.warning = true
18
+ desc 'Run tests'
19
+ task 'test' do
20
+ if (test_library = ENV['MOCHA_RUN_INTEGRATION_TESTS'])
21
+ Rake::Task["test:integration:#{test_library}"].invoke
22
+ else
23
+ Rake::Task['test:units'].invoke
24
+ Rake::Task['test:acceptance'].invoke
25
+ end
22
26
  end
23
27
 
24
- desc "Run integration tests"
25
- Rake::TestTask.new(:test_integration) do |t|
26
- t.libs << 'test'
27
- t.test_files = FileList['test/integration/*_test.rb']
28
- t.verbose = true
29
- t.warning = true
30
- end
28
+ namespace 'test' do
29
+ desc 'Run unit tests'
30
+ Rake::TestTask.new('units') do |t|
31
+ t.libs << 'test'
32
+ t.test_files = FileList['test/unit/**/*_test.rb']
33
+ t.verbose = true
34
+ t.warning = true
35
+ end
31
36
 
32
- desc "Run acceptance tests"
33
- Rake::TestTask.new(:test_acceptance) do |t|
34
- t.libs << 'test'
35
- t.test_files = FileList['test/acceptance/*_test.rb']
36
- t.verbose = true
37
- t.warning = true
38
- end
37
+ desc 'Run acceptance tests'
38
+ Rake::TestTask.new('acceptance') do |t|
39
+ t.libs << 'test'
40
+ t.test_files = FileList['test/acceptance/*_test.rb']
41
+ t.verbose = true
42
+ t.warning = true
43
+ end
39
44
 
40
- desc 'Generate RDoc'
41
- Rake::RDocTask.new do |task|
42
- task.main = 'README'
43
- task.title = "Mocha #{Mocha::VERSION}"
44
- task.rdoc_dir = 'doc'
45
- task.template = File.expand_path(File.join(File.dirname(__FILE__), "templates", "html_with_google_analytics"))
46
- task.rdoc_files.include('README', 'RELEASE', 'COPYING', 'MIT-LICENSE', 'agiledox.txt', 'lib/mocha/auto_verify.rb', 'lib/mocha/mock.rb', 'lib/mocha/expectation.rb', 'lib/mocha/object.rb', 'lib/mocha/parameter_matchers.rb', 'lib/mocha/parameter_matchers')
47
- end
48
- task :rdoc => :examples
45
+ desc 'Run each test in isolation'
46
+ task 'isolated' do
47
+ test_files = FileList['test/unit/**/*_test.rb', 'test/acceptance/*_test.rb']
48
+ failed_tests = []
49
49
 
50
- desc "Upload RDoc to RubyForge"
51
- task :publish_rdoc => [:rdoc, :examples] do
52
- Rake::SshDirPublisher.new("jamesmead@rubyforge.org", "/var/www/gforge-projects/mocha", "doc").upload
53
- end
50
+ test_files.each do |test_file|
51
+ puts "\n=== Running #{test_file} in isolation ==="
52
+ system("ruby -Itest -w #{test_file}") || (failed_tests << test_file)
53
+ end
54
54
 
55
- desc "Generate agiledox-like documentation for tests"
56
- file 'agiledox.txt' do
57
- File.open('agiledox.txt', 'w') do |output|
58
- tests = FileList['test/**/*_test.rb']
59
- tests.each do |file|
60
- m = %r".*/([^/].*)_test.rb".match(file)
61
- output << m[1]+" should:\n"
62
- test_definitions = File::readlines(file).select {|line| line =~ /.*def test.*/}
63
- test_definitions.sort.each do |definition|
64
- m = %r"test_(should_)?(.*)".match(definition)
65
- output << " - "+m[2].gsub(/_/," ") << "\n"
66
- end
55
+ if failed_tests.any?
56
+ puts "\n❌ #{failed_tests.size} test file(s) failed:"
57
+ failed_tests.each { |f| puts " - #{f}" }
58
+ exit 1
59
+ else
60
+ puts "\n✅ All #{test_files.size} test files passed in isolation!"
67
61
  end
68
62
  end
69
- end
70
63
 
71
- desc "Convert example ruby files to syntax-highlighted html"
72
- task :examples do
73
- $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "vendor", "coderay-0.7.4.215", "lib"))
74
- require 'coderay'
75
- mkdir_p 'doc/examples'
76
- File.open('doc/examples/coderay.css', 'w') do |output|
77
- output << CodeRay::Encoders[:html]::CSS.new.stylesheet
64
+ namespace 'integration' do
65
+ desc 'Run Minitest integration tests (intended to be run in its own process)'
66
+ Rake::TestTask.new('minitest') do |t|
67
+ t.libs << 'test'
68
+ t.test_files = FileList['test/integration/minitest_test.rb']
69
+ t.verbose = true
70
+ t.warning = true
71
+ end
72
+
73
+ desc 'Run Test::Unit integration tests (intended to be run in its own process)'
74
+ Rake::TestTask.new('test-unit') do |t|
75
+ t.libs << 'test'
76
+ t.test_files = FileList['test/integration/test_unit_test.rb']
77
+ t.verbose = true
78
+ t.warning = true
79
+ end
78
80
  end
79
- ['mocha', 'stubba', 'misc'].each do |filename|
80
- File.open("doc/examples/#{filename}.html", 'w') do |file|
81
- file << "<html>"
82
- file << "<head>"
83
- file << %q(<link rel="stylesheet" media="screen" href="coderay.css" type="text/css">)
84
- file << "</head>"
85
- file << "<body>"
86
- file << CodeRay.scan_file("examples/#{filename}.rb").html.div
87
- file << "</body>"
88
- file << "</html>"
81
+
82
+ # require 'rcov/rcovtask'
83
+ # Rcov::RcovTask.new('coverage') do |t|
84
+ # t.libs << 'test'
85
+ # t.test_files = unit_tests + acceptance_tests
86
+ # t.verbose = true
87
+ # t.warning = true
88
+ # t.rcov_opts << '--sort coverage'
89
+ # t.rcov_opts << '--xref'
90
+ # end
91
+
92
+ desc 'Run performance tests'
93
+ task 'performance' do
94
+ require File.join(File.dirname(__FILE__), 'test', 'acceptance', 'stubba_example_test')
95
+ require File.join(File.dirname(__FILE__), 'test', 'acceptance', 'mocha_example_test')
96
+ iterations = 1000
97
+ puts "\nBenchmarking with #{iterations} iterations..."
98
+ [MochaExampleTest, StubbaExampleTest].each do |test_case|
99
+ puts "#{test_case}: #{benchmark_test_case(test_case, iterations)} seconds."
89
100
  end
90
101
  end
91
102
  end
92
103
 
93
- Gem::manage_gems
94
-
95
- specification = Gem::Specification.new do |s|
96
- s.name = "mocha"
97
- s.summary = "Mocking and stubbing library"
98
- s.version = Mocha::VERSION
99
- s.platform = Gem::Platform::RUBY
100
- s.author = 'James Mead'
101
- s.description = <<-EOF
102
- Mocking and stubbing library with JMock/SchMock syntax, which allows mocking and stubbing of methods on real (non-mock) classes.
103
- EOF
104
- s.email = 'mocha-developer@rubyforge.org'
105
- s.homepage = 'http://mocha.rubyforge.org'
106
- s.rubyforge_project = 'mocha'
107
-
108
- s.has_rdoc = true
109
- s.extra_rdoc_files = ['README', 'COPYING']
110
- s.rdoc_options << '--title' << 'Mocha' << '--main' << 'README' << '--line-numbers'
111
-
112
- s.autorequire = 'mocha'
113
- s.add_dependency('rake')
114
- s.files = FileList['{lib,test,examples}/**/*.rb', '[A-Z]*'].exclude('TODO').to_a
104
+ desc 'Run linters'
105
+ task 'lint' do
106
+ if defined?(RuboCop::RakeTask)
107
+ RuboCop::RakeTask.new
108
+ Rake::Task['rubocop'].invoke
109
+ else
110
+ puts 'RuboCop not available - skipping linting'
111
+ end
115
112
  end
116
113
 
117
- Rake::GemPackageTask.new(specification) do |package|
118
- package.need_zip = true
119
- package.need_tar = true
114
+ def benchmark_test_case(klass, iterations) # rubocop:disable Metrics/AbcSize
115
+ require 'benchmark'
116
+ require 'mocha/detection/minitest'
117
+
118
+ if defined?(Minitest)
119
+ minitest_version = Gem::Version.new(Mocha::Detection::Minitest.version)
120
+ if Gem::Requirement.new('>= 5.0.0').satisfied_by?(minitest_version)
121
+ run_method = Gem::Requirement.new('>= 6.0.0').satisfied_by?(minitest_version) ? :run_suite : :run
122
+ Minitest.seed = 1
123
+ result = Benchmark.realtime { iterations.times { |_i| klass.public_send(run_method, Minitest::CompositeReporter.new) } }
124
+ Minitest::Runnable.runnables.delete(klass)
125
+ result
126
+ else
127
+ Minitest::Unit.output = StringIO.new
128
+ Benchmark.realtime { iterations.times { |_i| Minitest::Unit.new.run([klass]) } }
129
+ end
130
+ else
131
+ load 'test/unit/ui/console/testrunner.rb' unless defined?(Test::Unit::UI::Console::TestRunner)
132
+ unless @silent_option
133
+ begin
134
+ load 'test/unit/ui/console/outputlevel.rb' unless defined?(Test::Unit::UI::Console::OutputLevel::SILENT)
135
+ @silent_option = { output_level: Test::Unit::UI::Console::OutputLevel::SILENT }
136
+ rescue LoadError
137
+ @silent_option = Test::Unit::UI::SILENT
138
+ end
139
+ end
140
+ Benchmark.realtime { iterations.times { Test::Unit::UI::Console::TestRunner.run(klass, @silent_option) } }
141
+ end
120
142
  end
143
+ if ENV['MOCHA_GENERATE_DOCS']
144
+ require 'yard'
121
145
 
122
- task :verify_user do
123
- raise "RUBYFORGE_USER environment variable not set!" unless ENV['RUBYFORGE_USER']
124
- end
146
+ namespace :docs do
147
+ desc 'Remove generated documentation'
148
+ task :clobber do
149
+ `rm -rf ./docs`
150
+ end
125
151
 
126
- task :verify_password do
127
- raise "RUBYFORGE_PASSWORD environment variable not set!" unless ENV['RUBYFORGE_PASSWORD']
128
- end
152
+ desc 'Generate documentation'
153
+ YARD::Rake::YardocTask.new(:generate) do |task|
154
+ task.options = ['--title', "Mocha #{Mocha::VERSION}", '--fail-on-warning']
155
+ end
156
+
157
+ desc 'Ensure custom domain remains in place for docs on GitHub Pages'
158
+ task :ensure_cname do
159
+ `git checkout docs/CNAME`
160
+ end
129
161
 
130
- desc "Publish package files on RubyForge."
131
- task :publish_packages => [:verify_user, :verify_password, :package] do
132
- $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "vendor", "meta_project-0.4.15", "lib"))
133
- require 'meta_project'
134
- require 'rake/contrib/xforge'
135
- release_files = FileList[
136
- "pkg/mocha-#{Mocha::VERSION}.gem",
137
- "pkg/mocha-#{Mocha::VERSION}.tgz",
138
- "pkg/mocha-#{Mocha::VERSION}.zip"
139
- ]
140
-
141
- Rake::XForge::Release.new(MetaProject::Project::XForge::RubyForge.new('mocha')) do |release|
142
- release.user_name = ENV['RUBYFORGE_USER']
143
- release.password = ENV['RUBYFORGE_PASSWORD']
144
- release.files = release_files.to_a
145
- release.release_name = "Mocha #{Mocha::VERSION}"
146
- release.release_changes = ''
147
- release.release_notes = ''
162
+ desc 'Ensure custom JavaScript files remain in place for docs on GitHub Pages'
163
+ task :ensure_js do
164
+ `git checkout docs/js/app.js`
165
+ `git checkout docs/js/jquery.js`
166
+ end
167
+
168
+ desc 'Check documentation coverage'
169
+ task :coverage do
170
+ stats_output = `yard stats --list-undoc`
171
+ puts stats_output
172
+
173
+ match = stats_output.match(/(?<coverage_percentage>\d+\.\d+)% documented/);
174
+ abort 'Error: Could not determine documentation coverage.' unless match
175
+
176
+ coverage_percentage = match[:coverage_percentage].to_f
177
+ minimum_percentage = 100.0
178
+
179
+ if coverage_percentage < minimum_percentage
180
+ abort "Documentation coverage is #{coverage_percentage}%, which is below the required #{minimum_percentage}%."
181
+ else
182
+ puts "Documentation coverage is #{coverage_percentage}%, which is at or above the required #{minimum_percentage}%."
183
+ end
184
+ end
148
185
  end
186
+
187
+ desc 'Prepare documentation for publication on GitHub Pages'
188
+ task 'docs' => %w[docs:clobber docs:generate docs:ensure_cname docs:ensure_js]
149
189
  end
190
+
191
+ task 'release' => ['default', 'rubygems:release']
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '../'
4
+
5
+ group :development do
6
+ gem 'rake'
7
+ gem 'minitest'
8
+ end
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '../'
4
+
5
+ group :development do
6
+ gem 'rake'
7
+ gem 'rubocop'
8
+ gem 'rubocop-rake'
9
+ end
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '../'
4
+
5
+ group :development do
6
+ gem 'rake'
7
+ gem 'test-unit'
8
+ end
@@ -1,35 +1,21 @@
1
- require 'mocha/class_method'
1
+ # frozen_string_literal: true
2
2
 
3
- module Mocha
3
+ require 'mocha/stubbed_method'
4
4
 
5
- class AnyInstanceMethod < ClassMethod
6
-
7
- def unstub
8
- remove_new_method
9
- restore_original_method
10
- stubbee.any_instance.reset_mocha
11
- end
12
-
13
- def mock
14
- stubbee.any_instance.mocha
15
- end
16
-
17
- def hide_original_method
18
- stubbee.class_eval "alias_method :#{hidden_method}, :#{method}" if stubbee.method_defined?(method)
19
- end
5
+ module Mocha
6
+ class AnyInstanceMethod < StubbedMethod
7
+ private
20
8
 
21
- def define_new_method
22
- stubbee.class_eval "def #{method}(*args, &block); self.class.any_instance.mocha.method_missing(:#{method}, *args, &block); end"
9
+ def stubbee
10
+ stubba_object.any_instance
23
11
  end
24
12
 
25
- def remove_new_method
26
- stubbee.class_eval "remove_method :#{method}"
13
+ def stubbee_method(method_name)
14
+ stubba_object.instance_method(method_name)
27
15
  end
28
16
 
29
- def restore_original_method
30
- stubbee.class_eval "alias_method :#{method}, :#{hidden_method}; remove_method :#{hidden_method}" if stubbee.method_defined?(hidden_method)
17
+ def original_method_owner
18
+ stubba_object
31
19
  end
32
-
33
20
  end
34
-
35
- end
21
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mocha
4
+ class AnyInstanceReceiver
5
+ def initialize(klass)
6
+ @klass = klass
7
+ end
8
+
9
+ def mocks
10
+ klass = @klass
11
+ mocks = []
12
+ while klass
13
+ mocha = klass.any_instance.mocha(instantiate: false)
14
+ mocks << mocha if mocha
15
+ klass = klass.superclass
16
+ end
17
+ mocks
18
+ end
19
+ end
20
+ end
data/lib/mocha/api.rb ADDED
@@ -0,0 +1,213 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mocha/ruby_version'
4
+ require 'mocha/parameter_matchers'
5
+ require 'mocha/hooks'
6
+ require 'mocha/mockery'
7
+ require 'mocha/sequence'
8
+ require 'mocha/object_methods'
9
+ require 'mocha/class_methods'
10
+
11
+ module Mocha
12
+ # Methods added to +Test::Unit::TestCase+, +Minitest::Unit::TestCase+ or equivalent.
13
+ # The mock creation methods are {#mock}, {#stub} and {#stub_everything}, all of which return a #{Mock}
14
+ # which can be further modified by {Mock#responds_like} and {Mock#responds_like_instance_of} methods,
15
+ # both of which return a {Mock}, too, and can therefore, be chained to the original creation methods.
16
+ #
17
+ # {Mock#responds_like} and {Mock#responds_like_instance_of} force the mock to indicate what it is
18
+ # supposed to be mocking, thus making it a safer verifying mock. They check that the underlying +responder+
19
+ # will actually respond to the methods being stubbed, throwing a +NoMethodError+ upon invocation otherwise.
20
+ #
21
+ # @example Verifying mock using {Mock#responds_like_instance_of}
22
+ # class Sheep
23
+ # def initialize
24
+ # raise "some awkward code we don't want to call"
25
+ # end
26
+ # def chew(grass); end
27
+ # end
28
+ #
29
+ # sheep = mock('sheep').responds_like_instance_of(Sheep)
30
+ # sheep.expects(:chew)
31
+ # sheep.expects(:foo)
32
+ # sheep.respond_to?(:chew) # => true
33
+ # sheep.respond_to?(:foo) # => false
34
+ # sheep.chew
35
+ # sheep.foo # => raises NoMethodError exception
36
+ module API
37
+ include ParameterMatchers::Methods
38
+ include Hooks
39
+
40
+ # @private
41
+ def self.included(_mod)
42
+ Object.include Mocha::ObjectMethods
43
+ Class.include Mocha::ClassMethods
44
+ end
45
+
46
+ # @private
47
+ def self.extended(mod)
48
+ included(mod)
49
+ end
50
+
51
+ # Builds a new mock object
52
+ #
53
+ # @return [Mock] a new mock object
54
+ #
55
+ # @overload def mock(name)
56
+ # @param [String, Symbol] name identifies mock object in error messages.
57
+ # @overload def mock(expected_methods_vs_return_values = {})
58
+ # @param [Hash] expected_methods_vs_return_values expected method name symbols as keys and corresponding return values as values - these expectations are setup as if {Mock#expects} were called multiple times.
59
+ # @overload def mock(name, expected_methods_vs_return_values = {})
60
+ # @param [String, Symbol] name identifies mock object in error messages.
61
+ # @param [Hash] expected_methods_vs_return_values expected method name symbols as keys and corresponding return values as values - these expectations are setup as if {Mock#expects} were called multiple times.
62
+ #
63
+ # @example Using expected_methods_vs_return_values Hash to setup expectations.
64
+ # def test_motor_starts_and_stops
65
+ # motor = mock('motor', start: true, stop: true)
66
+ # assert motor.start
67
+ # assert motor.stop
68
+ # # an error will be raised unless both Motor#start and Motor#stop have been called
69
+ # end
70
+ #
71
+ def mock(*arguments)
72
+ name = arguments.shift.to_s if arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
73
+ expectations = arguments.shift || {}
74
+ mock = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
75
+ mock.expects(expectations)
76
+ mock
77
+ end
78
+
79
+ # Builds a new mock object
80
+ #
81
+ # @return [Mock] a new mock object
82
+ #
83
+ # @overload def stub(name)
84
+ # @param [String, Symbol] name identifies mock object in error messages.
85
+ # @overload def stub(stubbed_methods_vs_return_values = {})
86
+ # @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {Mock#stubs} were called multiple times.
87
+ # @overload def stub(name, stubbed_methods_vs_return_values = {})
88
+ # @param [String, Symbol] name identifies mock object in error messages.
89
+ # @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {Mock#stubs} were called multiple times.
90
+ #
91
+ # @example Using stubbed_methods_vs_return_values Hash to setup stubbed methods.
92
+ # def test_motor_starts_and_stops
93
+ # motor = stub('motor', start: true, stop: true)
94
+ # assert motor.start
95
+ # assert motor.stop
96
+ # # an error will not be raised even if either Motor#start or Motor#stop has not been called
97
+ # end
98
+ def stub(*arguments)
99
+ name = arguments.shift.to_s if arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
100
+ expectations = arguments.shift || {}
101
+ stub = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
102
+ stub.stubs(expectations)
103
+ stub
104
+ end
105
+
106
+ # Builds a mock object that accepts calls to any method. By default it will return +nil+ for any method call.
107
+ #
108
+ # @return [Mock] a new mock object
109
+ #
110
+ # @overload def stub_everything(name)
111
+ # @param [String, Symbol] name identifies mock object in error messages.
112
+ # @overload def stub_everything(stubbed_methods_vs_return_values = {})
113
+ # @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {Mock#stubs} were called multiple times.
114
+ # @overload def stub_everything(name, stubbed_methods_vs_return_values = {})
115
+ # @param [String, Symbol] name identifies mock object in error messages.
116
+ # @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {Mock#stubs} were called multiple times.
117
+ #
118
+ # @example Ignore invocations of irrelevant methods.
119
+ # def test_motor_stops
120
+ # motor = stub_everything('motor', stop: true)
121
+ # assert_nil motor.irrelevant_method_1 # => no error raised
122
+ # assert_nil motor.irrelevant_method_2 # => no error raised
123
+ # assert motor.stop
124
+ # end
125
+ def stub_everything(*arguments)
126
+ name = arguments.shift if arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
127
+ expectations = arguments.shift || {}
128
+ stub = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
129
+ stub.stub_everything
130
+ stub.stubs(expectations)
131
+ stub
132
+ end
133
+
134
+ # Builds a new sequence which can be used to constrain the order in which expectations can occur.
135
+ #
136
+ # Specify that an expected invocation must occur within a named {Sequence} by calling {Expectation#in_sequence}
137
+ # on each expectation or by passing a block within which all expectations should be constrained by the {Sequence}.
138
+ #
139
+ # @param [String] name name of sequence
140
+ # @yield optional block within which expectations should be constrained by the sequence
141
+ # @return [Sequence] a new sequence
142
+ #
143
+ # @see Expectation#in_sequence
144
+ #
145
+ # @example Ensure methods on egg are invoked in correct order.
146
+ # breakfast = sequence('breakfast')
147
+ #
148
+ # egg = mock('egg')
149
+ # egg.expects(:crack).in_sequence(breakfast)
150
+ # egg.expects(:fry).in_sequence(breakfast)
151
+ # egg.expects(:eat).in_sequence(breakfast)
152
+ #
153
+ # @example Ensure methods across multiple objects are invoked in correct order.
154
+ # sequence = sequence(:task_order)
155
+ #
156
+ # task_one = mock("task_one")
157
+ # task_two = mock("task_two")
158
+ #
159
+ # task_one.expects(:execute).in_sequence(sequence)
160
+ # task_two.expects(:execute).in_sequence(sequence)
161
+ #
162
+ # task_one.execute
163
+ # task_two.execute
164
+ #
165
+ # @example Ensure methods on egg are invoked in the correct order using a block.
166
+ # egg = mock('egg')
167
+ # sequence('breakfast') do
168
+ # egg.expects(:crack)
169
+ # egg.expects(:fry)
170
+ # egg.expects(:eat)
171
+ # end
172
+ def sequence(name)
173
+ Sequence.new(name).tap do |seq|
174
+ Mockery.instance.sequences.push(seq)
175
+ begin
176
+ yield if block_given?
177
+ ensure
178
+ Mockery.instance.sequences.pop
179
+ end
180
+ end
181
+ end
182
+
183
+ # Builds a new state machine which can be used to constrain the order in which expectations can occur.
184
+ #
185
+ # Specify the initial state of the state machine by using {StateMachine#starts_as}.
186
+ #
187
+ # Specify that an expected invocation should change the state of the state machine by using {Expectation#then}.
188
+ #
189
+ # Specify that an expected invocation should be constrained to occur within a particular +state+ by using {Expectation#when}.
190
+ #
191
+ # A test can contain multiple state machines.
192
+ #
193
+ # @param [String] name name of state machine
194
+ # @return [StateMachine] a new state machine
195
+ #
196
+ # @see Expectation#then
197
+ # @see Expectation#when
198
+ # @see StateMachine
199
+ # @example Constrain expected invocations to occur in particular states.
200
+ # power = states('power').starts_as('off')
201
+ #
202
+ # radio = mock('radio')
203
+ # radio.expects(:switch_on).then(power.is('on'))
204
+ # radio.expects(:select_channel).with('BBC Radio 4').when(power.is('on'))
205
+ # radio.expects(:adjust_volume).with(+5).when(power.is('on'))
206
+ # radio.expects(:select_channel).with('BBC World Service').when(power.is('on'))
207
+ # radio.expects(:adjust_volume).with(-5).when(power.is('on'))
208
+ # radio.expects(:switch_off).then(power.is('off'))
209
+ def states(name)
210
+ Mockery.instance.new_state_machine(name)
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mocha
4
+ class ArgumentIterator
5
+ def initialize(argument)
6
+ @argument = argument
7
+ end
8
+
9
+ def each(&block)
10
+ if @argument.is_a?(Hash)
11
+ @argument.each(&block)
12
+ else
13
+ block.call(@argument)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mocha
4
+ class BacktraceFilter
5
+ LIB_DIRECTORY = File.expand_path(File.join(File.dirname(__FILE__), '..')) + File::SEPARATOR
6
+
7
+ def initialize(lib_directory = LIB_DIRECTORY)
8
+ @lib_directory = lib_directory
9
+ end
10
+
11
+ def filtered(backtrace)
12
+ backtrace.reject { |location| File.expand_path(location).start_with?(@lib_directory) }
13
+ end
14
+ end
15
+ end