simple_mock 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2012 Tate Johnson <tate@tatey.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # SimpleMock
2
+
3
+ [![Build Status](https://secure.travis-ci.org/tatey/simple_mock.png?branch=master)](http://travis-ci.org/tatey/simple_mock)
4
+
5
+ A fast, tiny (81 lines) hybrid mocking library. Mix classical mocking with real objects. There's no monkey patching `Object` or copying. Real objects are completely untainted. The interface is 100% compatible with [MiniTest::Mock](https://github.com/seattlerb/minitest) so there is nothing new to learn. SimpleMock's one and only dependancy is Ruby 1.9.2 or greater.
6
+
7
+ ## Installation
8
+
9
+ Add this to your project's Gemfile and run `$ bundle`.
10
+
11
+ ``` ruby
12
+ gem 'simple_mock', :group => :test
13
+ ```
14
+
15
+ SimpleMock is isolated so there is no need to set require to false.
16
+
17
+ ## Usage
18
+
19
+ ### Classical Mocking
20
+
21
+ A new SimpleMock object behaves identically to MiniTest::Mock.
22
+
23
+ ``` ruby
24
+ mock_model = SimpleMock.new
25
+ mock_model.expect :valid?, true
26
+
27
+ mock_model.valid? # => true
28
+
29
+ mock_model.verify # => true
30
+ ```
31
+
32
+ ### Hybrid Mocking
33
+
34
+ Pass an object to mix expectations with the real object's original behaviour.
35
+
36
+ ``` ruby
37
+ class Post < ActiveRecord::Base
38
+ validates :title, :presence => true
39
+ end
40
+
41
+ real_model = Post.new
42
+ mock_model = SimpleMock.new real_model
43
+ mock_model.expect :valid?, true
44
+
45
+ mock_model.valid? # => true
46
+ mock_model.create # => true
47
+
48
+ mock_model.verify # => true
49
+ ```
50
+
51
+ This is done with delegation, avoiding monkey patching and copying. The real object is completely untainted.
52
+
53
+ ``` ruby
54
+ mock_model.valid # => true
55
+ real_model.valid? # => false
56
+
57
+ real_model.object_id == mock_model.__getobj__.object_id # => true
58
+ ```
59
+
60
+ More documentation is available at [rubydoc.info](http://rubydoc.info/gems/simple_mock/frames).
61
+
62
+ ## Caveats
63
+
64
+ Like MiniTest::Mock, `#expect` and `#verify` are reserved methods. Expectations should not be defined on real objects which implement these methods. As an alternative, consider creating an anonymous class which inherits from SimpleDelegator.
65
+
66
+ ``` ruby
67
+ mock_class = Class.new SimpleDelegator do
68
+ def verify *args
69
+ true
70
+ end
71
+ end
72
+ mock_instance = mock_class.new MyRealClass.new
73
+ mock_instance.verify # => true
74
+ ```
75
+
76
+ SimpleMock does something similar to this under the hood.
77
+
78
+ ## Copyright
79
+
80
+ Copyright © 2012 Tate Johnson. SimpleMock is released under the MIT license. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'bundler/setup'
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new :test do |test|
6
+ test.libs << 'test'
7
+ test.pattern = 'test/**/*_test.rb'
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,37 @@
1
+ require 'delegate'
2
+ require 'forwardable'
3
+ require 'minitest/mock'
4
+
5
+ require 'simple_mock/mock_delegator'
6
+ require 'simple_mock/tracer'
7
+ require 'simple_mock/version'
8
+
9
+ module SimpleMock
10
+
11
+ # Returns a mock instance. For classicial mocking, call +new+ without
12
+ # an argument.
13
+ #
14
+ # mock = SimpleMock.new
15
+ # mock.expect :meaning_of_life, 42
16
+ # mock.meaning_of_life # => 42
17
+ # mock.verify # => true
18
+ #
19
+ # For hybrid mocking call +new+ with an +object+ argument. Hybrid mocking
20
+ # mixes expectations with real objects.
21
+ #
22
+ # mock = SimpleMock.new Array.new
23
+ # mock.expect :meaning_of_life, 42
24
+ # mock.meaning_of_life # => 42
25
+ # mock.push(1) # => [1]
26
+ # mock.verify # => true
27
+ #
28
+ # +MiniTest::Mock+ and +SimpleMock::MockDelegator+ have a 100% compatible API
29
+ # making no difference to the consumer.
30
+ def self.new object = nil
31
+ if object.nil?
32
+ MiniTest::Mock.new
33
+ else
34
+ MockDelegator.new object
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,44 @@
1
+ module SimpleMock
2
+ class MockDelegator < SimpleDelegator
3
+ extend Forwardable
4
+
5
+ attr_accessor :__tracer
6
+ delegate :verify => :__tracer
7
+
8
+ def initialize object
9
+ super
10
+ self.__tracer = Tracer.new
11
+ end
12
+
13
+ # Expect that method +name+ is called, optionally with +args+, and returns
14
+ # +retval+.
15
+ #
16
+ # mock.expect :meaning_of_life, 42
17
+ # mock.meaning_of_life # => 42
18
+ #
19
+ # mock.expect :do_something_with, true, [some_obj, true]
20
+ # mock.do_something_with some_obj, true # => true
21
+ #
22
+ # +args+ is compared to the expected args using case equality (ie, the
23
+ # '===' method), allowing for less specific expectations.
24
+ #
25
+ # mock.expect :uses_any_string, true, [String]
26
+ # mock.uses_any_string 'foo' # => true
27
+ # mock.verify # => true
28
+ #
29
+ # mock.expect :uses_one_string, true, ['foo']
30
+ # mock.uses_one_string 'bar' # => true
31
+ # mock.verify # => raises MockExpectationError
32
+ def expect name, retval, args = []
33
+ method_definition = Module.new do
34
+ define_method name do |*args, &block|
35
+ __tracer.assert name, args
36
+ retval
37
+ end
38
+ end
39
+ extend method_definition
40
+ __tracer.register name, args
41
+ self
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,36 @@
1
+ module SimpleMock
2
+ class Tracer
3
+ attr_accessor :actual_calls, :expected_calls
4
+
5
+ def initialize
6
+ self.actual_calls = {}
7
+ self.expected_calls = {}
8
+ end
9
+
10
+ def assert name, actual_args = []
11
+ expected_args = expected_calls[name]
12
+ unless expected_args.size == actual_args.size
13
+ raise ArgumentError, "mocked method #{name.inspect} expects #{expected_args.size} arguments, got #{actual_args.size}"
14
+ end
15
+ unless expected_args.zip(actual_args).all? { |e, a| e === a || e == a }
16
+ raise MockExpectationError, "mocked method #{name.inspect} called with unexpected arguments #{actual_args.inspect}"
17
+ end
18
+ actual_calls[name] = true
19
+ end
20
+
21
+ def register name, args = []
22
+ expected_calls[name] = args
23
+ end
24
+
25
+ # Verify that all methods were called as expected. Raises
26
+ # +MockExpectationError+ if not called as expected.
27
+ def verify
28
+ differences = expected_calls.keys - actual_calls.keys
29
+ if differences.any?
30
+ raise MockExpectationError, "expected #{differences.first.inspect}"
31
+ else
32
+ true
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleMock
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "simple_mock/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "simple_mock"
7
+ s.version = SimpleMock::VERSION
8
+ s.authors = ["Tate Johnson"]
9
+ s.email = ["tate@tatey.com"]
10
+ s.homepage = 'https://github.com/tatey/simple_mock'
11
+ s.summary = %q{A fast, tiny hybrid mocking library.}
12
+ s.description = %q{A fast, tiny hybrid mocking library. Mix classical mocking with real objects. There's no monkey patching `Object` or copying objects. Real objects are completely untainted.}
13
+
14
+ s.rubyforge_project = "simple_mock"
15
+
16
+ s.required_ruby_version = '>= 1.9.2'
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+
23
+ s.add_development_dependency 'rake'
24
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'minitest/autorun'
2
+ require 'simple_mock'
3
+
4
+ include SimpleMock
@@ -0,0 +1,62 @@
1
+ require 'helper'
2
+
3
+ class MockDelegatorTest < MiniTest::Unit::TestCase
4
+ def test_initialize_sets_delegate
5
+ object = Object.new
6
+ delegator = MockDelegator.new object
7
+ assert_equal object, delegator.__getobj__
8
+ end
9
+
10
+ def test_expect_returns_self
11
+ object = Object.new
12
+ delegator = MockDelegator.new object
13
+ assert_equal delegator, delegator.expect(:pop, 1)
14
+ end
15
+
16
+ def test_expect_defines_method_returning_value
17
+ array = Array.new
18
+ delegator = MockDelegator.new array
19
+ delegator.expect :pop, 1
20
+ assert_equal 1, delegator.pop
21
+ end
22
+
23
+ def test_expect_defines_method_with_argument_returning_value
24
+ array = Array.new
25
+ delegator = MockDelegator.new array
26
+ delegator.expect :push, [1, 2], [Fixnum]
27
+ assert_equal [1, 2], delegator.push(2)
28
+ end
29
+
30
+ def test_expect_calls_register_on_tracer
31
+ tracer = MiniTest::Mock.new
32
+ tracer.expect :register, true, [:plus_one, []]
33
+ delegator = MockDelegator.new Object.new
34
+ delegator.__tracer = tracer
35
+ delegator.expect :plus_one, 2
36
+ assert tracer.verify
37
+ end
38
+
39
+ def test_verify_is_forwarded_to_tracer
40
+ tracer = Class.new { define_method(:verify) { true } }.new
41
+ delegator = MockDelegator.new Object.new
42
+ delegator.__tracer = tracer
43
+ assert_equal true, delegator.verify
44
+ end
45
+
46
+ def test_method_is_forwarded_to_delegate
47
+ array = Array.new
48
+ delegator = MockDelegator.new array
49
+ assert delegator.respond_to?(:push)
50
+ assert_equal [1], delegator.push(1)
51
+ end
52
+
53
+ def test_method_calls_assert_on_tracer
54
+ tracer = MockDelegator.new Tracer.new
55
+ tracer.expect :assert, true, [:plus_one, []]
56
+ delegator = MockDelegator.new Object.new
57
+ delegator.__tracer = tracer
58
+ delegator.expect :plus_one, 2
59
+ delegator.plus_one
60
+ assert tracer.verify
61
+ end
62
+ end
@@ -0,0 +1,11 @@
1
+ require 'helper'
2
+
3
+ class SimpleMockTest < MiniTest::Unit::TestCase
4
+ def test_new_without_argument_returns_minitest_mock
5
+ assert_match 'MiniTest::Mock', SimpleMock.new.inspect
6
+ end
7
+
8
+ def test_new_with_argument_returns_mock_delegator
9
+ assert_instance_of SimpleMock::MockDelegator, SimpleMock.new(Object.new)
10
+ end
11
+ end
@@ -0,0 +1,43 @@
1
+ require 'helper'
2
+
3
+ class TracerTest < MiniTest::Unit::TestCase
4
+ def setup
5
+ @tracer = Tracer.new
6
+ end
7
+
8
+ def test_register_stores_expected_method_and_arguments
9
+ @tracer.register :plus_one, [Fixnum]
10
+ assert_equal [Fixnum], @tracer.expected_calls[:plus_one]
11
+ end
12
+
13
+ def test_assert_returns_true_when_methods_are_called_as_expected
14
+ @tracer.register :plus_one, [Fixnum]
15
+ assert @tracer.assert(:plus_one, [1])
16
+ assert @tracer.actual_calls[:plus_one]
17
+ end
18
+
19
+ def test_assert_raises_when_methods_are_called_with_wrong_number_of_arguments
20
+ @tracer.register :plus_one, [Fixnum, Fixnum]
21
+ e = assert_raises(ArgumentError) { @tracer.assert :plus_one, [1] }
22
+ assert_equal 'mocked method :plus_one expects 2 arguments, got 1', e.message
23
+ end
24
+
25
+ def test_assert_raises_when_methods_are_called_with_wrong_arguments
26
+ @tracer.register :plus_one, [Fixnum]
27
+ e = assert_raises(MockExpectationError) { @tracer.assert :plus_one, [String.new] }
28
+ assert_equal 'mocked method :plus_one called with unexpected arguments [""]', e.message
29
+ end
30
+
31
+ def test_verify_returns_true_when_methods_are_called_as_expected
32
+ @tracer.expected_calls = {:plus_one => [Fixnum]}
33
+ @tracer.actual_calls = {:plus_one => true}
34
+ assert @tracer.verify
35
+ end
36
+
37
+ def test_verify_raises_when_expected_methods_are_not_called
38
+ @tracer.expected_calls = {:plus_one => [Fixnum]}
39
+ @tracer.actual_calls = {:plus_two => true}
40
+ e = assert_raises(MockExpectationError) { @tracer.verify }
41
+ assert_equal 'expected :plus_one', e.message
42
+ end
43
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_mock
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tate Johnson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-19 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &70324357134640 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70324357134640
25
+ description: A fast, tiny hybrid mocking library. Mix classical mocking with real
26
+ objects. There's no monkey patching `Object` or copying objects. Real objects are
27
+ completely untainted.
28
+ email:
29
+ - tate@tatey.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - .gitignore
35
+ - .travis.yml
36
+ - Gemfile
37
+ - LICENSE
38
+ - README.md
39
+ - Rakefile
40
+ - lib/simple_mock.rb
41
+ - lib/simple_mock/mock_delegator.rb
42
+ - lib/simple_mock/tracer.rb
43
+ - lib/simple_mock/version.rb
44
+ - simple_mock.gemspec
45
+ - test/helper.rb
46
+ - test/unit/mock_delegator_test.rb
47
+ - test/unit/simple_mock_test.rb
48
+ - test/unit/tracer_test.rb
49
+ homepage: https://github.com/tatey/simple_mock
50
+ licenses: []
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: 1.9.2
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ segments:
68
+ - 0
69
+ hash: -790596087642070463
70
+ requirements: []
71
+ rubyforge_project: simple_mock
72
+ rubygems_version: 1.8.10
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: A fast, tiny hybrid mocking library.
76
+ test_files:
77
+ - test/helper.rb
78
+ - test/unit/mock_delegator_test.rb
79
+ - test/unit/simple_mock_test.rb
80
+ - test/unit/tracer_test.rb