motion-facon 0.5.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.
@@ -0,0 +1,19 @@
1
+ .repl_history
2
+ build
3
+ tags
4
+ app/pixate_code.rb
5
+ resources/*.nib
6
+ resources/*.momd
7
+ resources/*.storyboardc
8
+ .DS_Store
9
+ nbproject
10
+ .redcar
11
+ #*#
12
+ *~
13
+ *.sw[po]
14
+ .eprj
15
+ .sass-cache
16
+ .idea
17
+ build/
18
+ resources/**/*
19
+ db/schema.xcdatamodeld
@@ -0,0 +1,32 @@
1
+ === 0.5.0
2
+ * Added Ruby 1.9.2 compatibility. Thanks ymendel!
3
+ * Get rid of that dependency on hoe, use Bundler to manage gem release.
4
+
5
+ === 0.4.1 / 2008-12-05
6
+
7
+ * Added #times, #once and #never expectation matchers. Thanks raggi!
8
+ E.g.
9
+ @mock.should.receive(:call_me_thrice).times(3)
10
+ @mock.should.receive(:just_this_1_time).once
11
+ @mock.should.receive(:dont_even_think_about_it).never
12
+
13
+ === 0.4.0 / 2008-12-05
14
+
15
+ * Fix compatibility with Bacon 1.0 and 1.1.
16
+
17
+ === 0.3.1 / 2008-02-19
18
+
19
+ * Fixed a bug where mocks were not being teared down when there is a previous spec failure.
20
+
21
+ === 0.3 / 2008-02-18
22
+
23
+ * Fixed a bug with proxied methods not being cleared.
24
+ * Fixed a bug where the same mocks were repeatedly being added to $facon_mocks.
25
+
26
+ === 0.2 / 2008-02-13
27
+
28
+ * Use #after block to verify mocks so that the stack trace is more helpful (it now actually shows the line in the spec where the mock error occurred).
29
+
30
+ === 0.1 / 2008-02-09
31
+
32
+ * First release!
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in motion-motion-facon.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'rake'
8
+ end
@@ -0,0 +1,16 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ motion-facon (0.5.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ rake (0.9.2.2)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ motion-facon!
16
+ rake
@@ -0,0 +1,94 @@
1
+ MotionFacon
2
+ =====
3
+
4
+ MotionFacon is a port of Facon mocking library to RubyMotion platform. It brings mocking functionality to Bacon which is
5
+ the default (and only?) test framework for rubymotion.
6
+
7
+ I tried to make minimal changes to original library and will try to keep up with upstream.
8
+
9
+ Synopsis
10
+ --------
11
+
12
+ To use MotionFacon you need to install it with `gem install motion-facon` and then require it in you Rakefile with `require motion-facon.`
13
+
14
+ Alternatively you can add the following to your Gemfile `gem 'motion-facon'`.
15
+
16
+ You can now write [Bacon](https://github.com/chneukirchen/bacon) specs like this (in RSpec-like style):
17
+
18
+ ```ruby
19
+ describe 'PersonController' do
20
+ extend Facon::SpecHelpers
21
+
22
+ before do
23
+ @konata = mock('konata', :id => 1, :name => 'Konata Izumi')
24
+ @kagami = mock('kagami', :id => 2, :name => 'Kagami Hiiragi')
25
+ end
26
+
27
+ it "should find all people on GET to 'index'" do
28
+ Person.should.receive(:find).with(:all).and_return([@konata, @kagami])
29
+
30
+ Person.list
31
+ end
32
+
33
+ it "should find the person with id of 1 on Get to 'show/1'" do
34
+ Person.should.receive(:find).with(1).and_return(@konata)
35
+
36
+ Person.first
37
+ end
38
+ end
39
+ ```
40
+
41
+ For now, more examples can be found in the specs included with the Facon gem. I promise to get better examples into the documentation!
42
+
43
+ See Facon::Baconize for more documentation on using Facon with [Bacon](https://github.com/chneukirchen/bacon).
44
+
45
+ Requirements
46
+ ------------
47
+
48
+ * Recent version of RubyMotion. Tested against 1.35.
49
+
50
+
51
+ Todos
52
+ -----
53
+
54
+ * Keep up with upstream
55
+
56
+ Contributors
57
+ ------------
58
+
59
+ * [James Tucker](https://github.com/raggi) for #times, #once, #never expectation matchers.
60
+ * [Peter Kim](https://github.com/petejkim) for [MacBacon](https://github.com/alloy/MacBacon) support.
61
+ * [Yossef Mendelssohn](https://github.com/ymendel) for Ruby 1.9.2 compatibility fixes.
62
+
63
+ Thanks to
64
+ ---------
65
+
66
+ * [RSpec](http://rspec.info/) for creating spec/mocks, from which a lot of the code for Facon is stolen.
67
+ * [Christian Neukirchen](https://github.com/chneukirchen) for creating Bacon.
68
+ * [Cheah Chu Yeow](https://github.com/chuyeow) for the original Facon gem.
69
+
70
+ License
71
+ -------
72
+
73
+ (The MIT License)
74
+
75
+ Copyright (c) 2008 Cheah Chu Yeow
76
+
77
+ Permission is hereby granted, free of charge, to any person obtaining
78
+ a copy of this software and associated documentation files (the
79
+ 'Software'), to deal in the Software without restriction, including
80
+ without limitation the rights to use, copy, modify, merge, publish,
81
+ distribute, sublicense, and/or sell copies of the Software, and to
82
+ permit persons to whom the Software is furnished to do so, subject to
83
+ the following conditions:
84
+
85
+ The above copyright notice and this permission notice shall be
86
+ included in all copies or substantial portions of the Software.
87
+
88
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
89
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
90
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
91
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
92
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
93
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
94
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,13 @@
1
+ # -*- coding: utf-8 -*-
2
+ $:.unshift("/Library/RubyMotion/lib")
3
+ require 'motion/project'
4
+ require "bundler/gem_tasks"
5
+ require "bundler/setup"
6
+
7
+ $:.unshift("./lib/")
8
+ require "./lib/motion-facon"
9
+
10
+ Motion::Project::App.setup do |app|
11
+ # Use `rake config' to see complete project settings.
12
+ app.name = 'motion-facon'
13
+ end
@@ -0,0 +1,5 @@
1
+ class AppDelegate
2
+ def application(application, didFinishLaunchingWithOptions:launchOptions)
3
+ true
4
+ end
5
+ end
@@ -0,0 +1,31 @@
1
+ # Facon is a mocking library in the spirit of the Bacon spec library. Small,
2
+ # compact, and works with Bacon.
3
+ module Facon
4
+ end
5
+
6
+ unless defined?(Motion::Project::Config)
7
+ raise "This file must be required within a RubyMotion project Rakefile."
8
+ end
9
+
10
+ Motion::Project::App.setup do |app|
11
+ app.development do
12
+ base_path = "#{File.dirname(__FILE__)}"
13
+ files = []
14
+ files << 'motion-facon/mockable'
15
+ files << 'motion-facon/spec_helpers'
16
+ files << 'motion-facon/version'
17
+ files << 'motion-facon/error_generator'
18
+ files << 'motion-facon/expectation'
19
+ files << 'motion-facon/baconize'
20
+ files << 'motion-facon/mock'
21
+ files << 'motion-facon/proxy'
22
+
23
+
24
+
25
+ files.each do |file|
26
+ app.files.unshift File.expand_path "#{base_path}/#{file}.rb"
27
+ end
28
+
29
+ app.detect_dependencies = true
30
+ end
31
+ end
@@ -0,0 +1,96 @@
1
+ module Facon
2
+ # == Bacon integration
3
+ #
4
+ # To use Facon with Bacon, simply <code>require 'motion-facon'</code>. Facon injects
5
+ # itself into Bacon if it can find it, so all you have to do is to make sure
6
+ # you have Bacon and Facon available on the load path.
7
+ #
8
+ # == Example
9
+ #
10
+ # In <code>spec_helper.rb</code>:
11
+ # require 'rubygems'
12
+ # require 'bacon'
13
+ # require 'motion-facon'
14
+ #
15
+ # Simply <code>require</code> your <code>spec_helper.rb</code> in your specs and you are now
16
+ # able to create mocks and expectations:
17
+ #
18
+ # require '/path/to/spec_helper'
19
+ #
20
+ # describe 'My examples' do
21
+ # it "should allow mocks and expectations" do
22
+ # @mock = mock('test mock')
23
+ # @mock.should.receive(:message).and_return(:foo)
24
+ #
25
+ # do_something_with(@mock)
26
+ # end
27
+ # end
28
+ module Baconize
29
+
30
+ # Mixin intended for Bacon::Context so that it runs spec_verify on all mocks
31
+ # after each example.
32
+ module ContextExtensions
33
+ def self.included(base)
34
+ base.class_eval do
35
+ alias_method :it_without_mock_verification, :it
36
+ alias_method :it, :it_with_mock_verification
37
+ end
38
+ end
39
+
40
+ def setup_facon_mocks
41
+ $facon_mocks ||= []
42
+ end
43
+
44
+ def verify_facon_mocks
45
+ $facon_mocks.each { |mock| mock.spec_verify }
46
+ end
47
+
48
+ def teardown_facon_mocks
49
+ if $facon_mocks
50
+ $facon_mocks.each { |mock| mock.spec_reset }
51
+ $facon_mocks.clear
52
+ end
53
+ end
54
+
55
+ def it_with_mock_verification(description, &block)
56
+ @before.unshift(proc { setup_facon_mocks })
57
+ @after << proc { verify_facon_mocks }
58
+ it_without_mock_verification(description, &block)
59
+ ensure
60
+ teardown_facon_mocks
61
+ end
62
+ end
63
+
64
+ # Mixin intended for Bacon's Should class so that we can do
65
+ # mock.should.receive(:message) and mock.should.not.receive(:message).
66
+ module ShouldExtensions
67
+ def self.included(base)
68
+ # Remove Facon::Mockable methods we mixed in to Object, since we don't
69
+ # need those in the Should class.
70
+ base.class_eval do
71
+ [:"mock:",
72
+ :"stub!:",
73
+ :"should_receive:",
74
+ :"should_not_receive:",
75
+ :spec_verify,
76
+ :spec_reset,
77
+ :mock_proxy].each {|m| undef_method(m)}
78
+ end
79
+ end
80
+
81
+ def receive(method, &block)
82
+ Bacon::Counter[:requirements] += 1 # A should.receive expectation is also a Bacon requirement.
83
+ if @negated
84
+ @object.mock_proxy.add_negative_expectation(caller(1)[0], method, &block)
85
+ else
86
+ @object.mock_proxy.add_expectation(caller(1)[0], method, &block)
87
+ end
88
+ end
89
+
90
+ private
91
+ def mock_proxy
92
+ @mock_proxy ||= Proxy.new(@object, Mock === @object ? @object.name : @object.class.name)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,42 @@
1
+ module Facon
2
+ # A helper class for generating errors for expectation errors on mocks.
3
+ class ErrorGenerator
4
+ def initialize(target, name)
5
+ @target, @name = target, name
6
+ end
7
+
8
+ def raise_expectation_error(expectation)
9
+ message = "#{target_name} expected :#{expectation.method} with #{format_args(*expectation.argument_expectation)} #{format_count(expectation.expected_received_count)}, but received it #{format_count(expectation.actual_received_count)}"
10
+ raise(Facon::MockExpectationError, message)
11
+ end
12
+
13
+ def raise_unexpected_message_error(method, *args)
14
+ raise(Facon::MockExpectationError, "#{target_name} received unexpected message :#{method} with #{format_args(*args)}")
15
+ end
16
+
17
+ def raise_unexpected_message_args_error(expectation, *args)
18
+ message = "#{target_name} expected :#{expectation.method} with #{format_args(*expectation.argument_expectation)}, but received it with #{format_args(*args)}"
19
+ raise(Facon::MockExpectationError, message)
20
+ end
21
+
22
+ def raise_block_failed_error(method, exception_message)
23
+ message = "#{target_name} received :#{method} but passed block failed with: #{exception_message}"
24
+ raise(Facon::MockExpectationError, message)
25
+ end
26
+
27
+ private
28
+ def target_name
29
+ @name ? "Mock '#{@name}'" : @target.inspect
30
+ end
31
+
32
+ def format_args(*args)
33
+ return '(no args)' if args.empty?
34
+ return '(any args)' if args == [:any]
35
+ "(#{args.map { |a| a.inspect }.join(', ')})"
36
+ end
37
+
38
+ def format_count(count)
39
+ count == 1 ? '1 time' : "#{count} times"
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,143 @@
1
+ module Facon
2
+ # An Expectation, also know as a mock method, is an expectation that an object
3
+ # should receive a specific message during the execution of an example.
4
+ class Expectation
5
+
6
+ def raise_expectation_error(*args)
7
+ @error_generator.raise_expectation_error *args
8
+ end
9
+
10
+ def raise_block_failed_error(*args)
11
+ @error_generator.raise_block_failed_error *args
12
+ end
13
+
14
+ attr_reader :error_generator, :expectation_ordering, :expected_from, :method, :method_block, :expected_received_count, :actual_received_count, :argument_expectation
15
+
16
+ def initialize(error_generator, expectation_ordering, expected_from, method, method_block, expected_received_count = 1)
17
+ @error_generator = error_generator
18
+ @expectation_ordering = expectation_ordering
19
+ @expected_from = expected_from
20
+ @method = method
21
+ @method_block = method_block
22
+ @expected_received_count = expected_received_count
23
+
24
+ @argument_expectation = :any
25
+ @exception_to_raise = nil
26
+ @symbol_to_throw = nil
27
+ @actual_received_count = 0
28
+ @args_to_yield = []
29
+ end
30
+
31
+ # Sets up the expected method to return the given value.
32
+ def and_return(value)
33
+ raise MockExpectationError, 'Ambiguous return expectation' unless @method_block.nil?
34
+
35
+ @return_block = proc { value }
36
+ end
37
+
38
+ # Sets up the expected method to yield with the given arguments.
39
+ def and_yield(*args)
40
+ @args_to_yield << args
41
+ self
42
+ end
43
+
44
+ # Sets up the expected method to raise the given <code>exception</code>
45
+ # (default: Exception).
46
+ def and_raise(exception = Exception)
47
+ @exception_to_raise = exception
48
+ end
49
+
50
+ # Sets up the expected method to throw the given <code>symbol</code>.
51
+ def and_throw(sym)
52
+ @symbol_to_throw = sym
53
+ end
54
+
55
+ def with(*args, &block)
56
+ @method_block = block if block
57
+ @argument_expectation = args
58
+ self
59
+ end
60
+
61
+ def invoke(args, block)
62
+ begin
63
+ raise @exception_to_raise unless @exception_to_raise.nil?
64
+ throw @symbol_to_throw unless @symbol_to_throw.nil?
65
+
66
+ return_value = if !@method_block.nil?
67
+ invoke_method_block(args)
68
+ elsif @args_to_yield.size > 0
69
+ @args_to_yield.each { |curr_args| block.call(*curr_args) }
70
+ else
71
+ nil
72
+ end
73
+
74
+ if defined?(@return_block) && @return_block
75
+ args << block unless block.nil?
76
+ @return_block.call(*args)
77
+ else
78
+ return_value
79
+ end
80
+ ensure
81
+ @actual_received_count += 1
82
+ end
83
+ end
84
+
85
+ # Returns true if this expectation has been met.
86
+ # TODO at_least and at_most conditions
87
+ def met?
88
+ return true if @expected_received_count == :any ||
89
+ @expected_received_count == @actual_received_count
90
+
91
+ raise_expectation_error(self)
92
+ end
93
+
94
+ # Returns true if the given <code>method</code> and arguments match this
95
+ # Expectation.
96
+ def matches(method, args)
97
+ @method == method && check_arguments(args)
98
+ end
99
+
100
+ # Returns true if the given <code>method</code> matches this Expectation,
101
+ # but the given arguments don't.
102
+ def matches_name_but_not_args(method, args)
103
+ @method == method && !check_arguments(args)
104
+ end
105
+
106
+ def negative_expectation_for?(method)
107
+ false
108
+ end
109
+
110
+ def times(val)
111
+ @expected_received_count = val
112
+ self
113
+ end
114
+
115
+ def once; times(1); end
116
+
117
+ def never; times(0); end
118
+
119
+ private
120
+ def check_arguments(args)
121
+ case @argument_expectation
122
+ when :any then true
123
+ when args then true
124
+ end
125
+ end
126
+
127
+ def invoke_method_block(args)
128
+ @method_block.call(*args)
129
+ rescue => e
130
+ raise_block_failed_error(@method, e.message)
131
+ end
132
+ end
133
+
134
+ class NegativeExpectation < Expectation
135
+ def initialize(error_generator, expectation_ordering, expected_from, method, method_block, expected_received_count = 0)
136
+ super(error_generator, expectation_ordering, expected_from, method, method_block, expected_received_count)
137
+ end
138
+
139
+ def negative_expectation_for?(method)
140
+ @method == method
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,39 @@
1
+ module Facon
2
+ # Error returned when an expectation on a mock is not satisfied.
3
+ class MockExpectationError < StandardError
4
+ end
5
+
6
+ # A mock object is a 'fake' object on which you can impose simulated behavior.
7
+ # Defining expectations and stubs on mock objects allows you to specify
8
+ # object collaboration without needing to actually instantiate those
9
+ # collaborative objects.
10
+ #
11
+ # == Examples
12
+ #
13
+ # mock = mock('A name')
14
+ # mock = mock('Mock person', :name => 'Konata', :sex => 'female')
15
+ class Mock
16
+ attr_accessor :name
17
+
18
+ def initialize(name, stubs = {})
19
+ @name = name
20
+ stub_out(stubs)
21
+ end
22
+
23
+ def method_missing(method, *args, &block)
24
+ super(method, *args, &block)
25
+ rescue NameError
26
+ # An unexpected method was called on this mock.
27
+ mock_proxy.raise_unexpected_message_error(method, *args)
28
+ end
29
+
30
+ private
31
+
32
+ # Stubs out all the given stubs.
33
+ def stub_out(stubs)
34
+ stubs.each_pair do |method, response|
35
+ stub!(method).and_return(response)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,43 @@
1
+ module Facon
2
+ # A module containing convenient methods for creating mocks, stubs and
3
+ # expectations.
4
+ module Mockable
5
+
6
+ # Shortcut for creating a Facon::Mock instance.
7
+ #
8
+ # == Example
9
+ #
10
+ # mock = mock('test mock', :foo => 'bar')
11
+ # mock.foo # => 'bar'
12
+ def mock(name, stubs = {})
13
+ Mock.new(name, stubs)
14
+ end
15
+
16
+ def stub!(method)
17
+ mock_proxy.add_stub(caller(1)[0], method)
18
+ end
19
+
20
+ def should_receive(method, &block)
21
+ mock_proxy.add_expectation(caller(1)[0], method, &block)
22
+ end
23
+
24
+ def should_not_receive(method, &block)
25
+ mock_proxy.add_negative_expectation(caller(1)[0], method, &block)
26
+ end
27
+
28
+ # Verifies that the expectations set on this mock are all met, otherwise
29
+ # raises a MockExpectationError.
30
+ def spec_verify
31
+ mock_proxy.verify
32
+ end
33
+
34
+ def spec_reset
35
+ mock_proxy.reset
36
+ end
37
+
38
+ # Returns the mock proxy object.
39
+ def mock_proxy
40
+ @mock_proxy ||= Proxy.new(self, Mock === self ? @name : self.class.name)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,132 @@
1
+ module Facon
2
+ # A proxy for mock objects. Stubs and expectations are set on this proxy.
3
+ class Proxy
4
+ def raise_unexpected_message_error(*args)
5
+ @error_generator.raise_unexpected_message_error *args
6
+ end
7
+
8
+ def raise_unexpected_message_args_error(*args)
9
+ @error_generator.raise_unexpected_message_args_error *args
10
+ end
11
+
12
+ def initialize(target, name)
13
+ @target, @name = target, name
14
+ @expectations = []
15
+ @stubs = []
16
+ @proxied_methods = []
17
+ @error_generator = ErrorGenerator.new(target, name)
18
+ @expectation_ordering = nil unless defined?(@expectation_ordering)
19
+ end
20
+
21
+ def add_stub(expected_from, method)
22
+ add_method(method)
23
+
24
+ # A stub is really an expectation that can be called any number of times.
25
+ @stubs.unshift(Expectation.new(@error_generator, @expectation_ordering, expected_from, method, nil, :any))
26
+ @stubs.first
27
+ end
28
+
29
+ def add_expectation(expected_from, method, &block)
30
+ add_method(method)
31
+
32
+ @expectations << Expectation.new(@error_generator, @expectation_ordering, expected_from, method, (block_given? ? block : nil), 1)
33
+ @expectations.last
34
+ end
35
+
36
+ def add_negative_expectation(expected_from, method, &block)
37
+ add_method(method)
38
+
39
+ @expectations << NegativeExpectation.new(@error_generator, @expectation_ordering, expected_from, method, (block_given? ? block : nil))
40
+ @expectations.last
41
+ end
42
+
43
+ def message_received(method, *args, &block)
44
+ if expectation = find_matching_expectation(method, *args)
45
+ expectation.invoke(args, block)
46
+ elsif stub = find_matching_method_stub(method, *args)
47
+ stub.invoke([], block)
48
+ elsif expectation = find_almost_matching_expectation(method, *args)
49
+ raise_unexpected_message_args_error(expectation, *args) unless has_negative_expectation?(method)
50
+ else
51
+ @target.send(:method_missing, method, *args, &block)
52
+ end
53
+ end
54
+
55
+ def verify
56
+ @expectations.each { |expectation| expectation.met? }
57
+ ensure
58
+ reset
59
+ end
60
+
61
+ def reset
62
+ @expectations.clear
63
+ @stubs.clear
64
+ reset_proxied_methods
65
+ @proxied_methods.clear
66
+ end
67
+
68
+ private
69
+ def add_method(method)
70
+ $facon_mocks << @target unless $facon_mocks.nil? || $facon_mocks.detect { |m| m.equal?(@target) }
71
+ define_expected_method(method)
72
+ end
73
+
74
+ # Defines an expected method that simply calls the
75
+ # <code>message_received</code> method.
76
+ def define_expected_method(method)
77
+ if @target.respond_to?(method) && !metaclass.method_defined?(munge(method))
78
+ munged_method = munge(method)
79
+ metaclass.instance_eval do
80
+ alias_method munged_method, method if method_defined?(method.to_s)
81
+ end
82
+ @proxied_methods << method
83
+ end
84
+
85
+ #fixme: (__FILE__, __LINE__)
86
+ metaclass.class_eval do
87
+ define_method :"#{method}" do |*args, &block|
88
+ mock_proxy.message_received(:"#{method}", *args, &block)
89
+ end
90
+ end
91
+ end
92
+
93
+ def munge(method)
94
+ "proxied_by_facon__#{method.to_s}".to_sym
95
+ end
96
+
97
+ def reset_proxied_methods
98
+ @proxied_methods.each do |method|
99
+ munged_method = munge(method)
100
+ metaclass.instance_eval do
101
+ if method_defined?(munged_method.to_s)
102
+ alias_method method, munged_method
103
+ undef_method munged_method
104
+ else
105
+ undef_method method
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ def metaclass
112
+ (class << @target; self; end)
113
+ end
114
+
115
+
116
+ def find_matching_expectation(method, *args)
117
+ @expectations.find { |expectation| expectation.matches(method, args) }
118
+ end
119
+
120
+ def find_almost_matching_expectation(method, *args)
121
+ @expectations.find { |expectation| expectation.matches_name_but_not_args(method, args) }
122
+ end
123
+
124
+ def find_matching_method_stub(method, *args)
125
+ @stubs.find { |stub| stub.matches(method, args) }
126
+ end
127
+
128
+ def has_negative_expectation?(method)
129
+ @expectations.find { |expectation| expectation.negative_expectation_for?(method) }
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,9 @@
1
+ module Facon
2
+ module SpecHelpers
3
+ def self.extended(base)
4
+ Object.class_eval { include Facon::Mockable }
5
+ base.class.class_eval { include Facon::Baconize::ContextExtensions }
6
+ Should.class_eval { include Facon::Baconize::ShouldExtensions }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module MotionFacon
2
+ VERSION = '0.5.0.1'
3
+ end
@@ -0,0 +1,19 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+ require 'motion-facon/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'motion-facon'
6
+ s.version = MotionFacon::VERSION
7
+ s.authors = ['chuyeow', 'svyatogor']
8
+ s.email = ['chuyeow@gmail.com', 'svyatogor@gmail.com']
9
+ s.homepage = 'https://github.com/svyatogor/motion-facon'
10
+ s.summary = %q{Tiny mocking library.}
11
+ s.description = %q{Port of facon mocking library to rubymotion.}
12
+
13
+ s.rubyforge_project = 'motion-facon'
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features,app}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ['lib']
19
+ end
@@ -0,0 +1,35 @@
1
+ describe "Facon::Baconize" do
2
+ extend Facon::SpecHelpers
3
+
4
+ before do
5
+ @mock = Facon::Mock.new('test mock')
6
+ end
7
+
8
+ it "should make the #receive instance method available to Should" do
9
+ methods = Should.public_instance_methods.collect { |m| m.to_s }
10
+ methods.should.include?('receive:')
11
+ end
12
+
13
+ it "should allow expectations on mocks with should.receive(:message)" do
14
+ @mock.should.receive(:message).and_return(:foo)
15
+
16
+ @mock.message.should == :foo
17
+ end
18
+
19
+ it "should allow expectations on mocks with should.not.receive(:message)" do
20
+ @mock.should.not.receive(:message)
21
+
22
+ @mock.to_s
23
+ # FIXME: needs a better test on the actual error raised, but the
24
+ # instance_eval in it() makes it hard.
25
+ end
26
+
27
+ it "should allow expectations on arbitrary objects with should.receive(:message)" do
28
+ Object.should.receive(:message).and_return(:foo)
29
+ @object = Object.new
30
+ @object.should.receive(:message).and_return(:bar)
31
+
32
+ Object.message.should == :foo
33
+ @object.message.should == :bar
34
+ end
35
+ end
@@ -0,0 +1,183 @@
1
+ describe "A mock object" do
2
+ before do
3
+ @mock = Facon::Mock.new('test mock')
4
+ end
5
+
6
+ after do
7
+ @mock.spec_reset
8
+ end
9
+
10
+ def verify_mock
11
+ lambda { @mock.spec_verify }.should.not.raise(Facon::MockExpectationError)
12
+ end
13
+
14
+ it "should pass when not receiving message specified as not to be received" do
15
+ @mock.should_not_receive(:not_expected)
16
+
17
+ verify_mock
18
+ end
19
+
20
+ it "should pass when receiving message specified as not to be received with different args" do
21
+ @mock.should_not_receive(:message).with(:not_this)
22
+ @mock.should_receive(:message).with(:but_this)
23
+ @mock.message(:but_this)
24
+
25
+ verify_mock
26
+ end
27
+
28
+ it "should raise a MockExpectationError when receiving message specified as not to be received" do
29
+ @mock.should_not_receive(:not_expected)
30
+ @mock.not_expected
31
+
32
+ lambda { @mock.spec_verify }.should.raise(Facon::MockExpectationError).message.should == "Mock 'test mock' expected :not_expected with (any args) 0 times, but received it 1 time"
33
+ end
34
+
35
+ it "should raise a MockExpectationError when receiving message specified as not to be received with arguments" do
36
+ @mock.should_not_receive(:not_expected).with(:unexpected_arg)
37
+ @mock.not_expected(:unexpected_arg)
38
+
39
+ lambda { @mock.spec_verify }.should.raise(Facon::MockExpectationError).message.should == "Mock 'test mock' expected :not_expected with (:unexpected_arg) 0 times, but received it 1 time"
40
+ end
41
+
42
+ it "should pass when receiving message specified as not to be received, but with wrong arguments" do
43
+ @mock.should_not_receive(:not_expected).with(:unexpected_arg)
44
+ @mock.not_expected(:wrong_arg)
45
+
46
+ verify_mock
47
+ end
48
+
49
+ it "should raise a MockExpectationError when receiving message specified as to be received is not called" do
50
+ @mock.should_receive(:expected_message)
51
+
52
+ lambda { @mock.spec_verify }.should.raise(Facon::MockExpectationError).message.should == "Mock 'test mock' expected :expected_message with (any args) 1 time, but received it 0 times"
53
+ end
54
+
55
+ it "should raise a MockExpectationError when receiving message specified as to be received, but with wrong arguments" do
56
+ @mock.should_receive(:expected_message).with(:expected_arg)
57
+
58
+ lambda {
59
+ @mock.expected_message(:unexpected_arg)
60
+ }.should.raise(Facon::MockExpectationError).message.should == "Mock 'test mock' expected :expected_message with (:expected_arg), but received it with (:unexpected_arg)"
61
+ end
62
+
63
+ it "should raise a MockExpectationError when receiving an unexpected message" do
64
+ lambda {
65
+ @mock.not_expected
66
+ }.should.raise(Facon::MockExpectationError).message.should == "Mock 'test mock' received unexpected message :not_expected with (no args)"
67
+ end
68
+
69
+ it "should raise a MockExpectationError when receiving an unexpected message with arguments" do
70
+ lambda {
71
+ @mock.not_expected(:foo, :bar)
72
+ }.should.raise(Facon::MockExpectationError).message.should == "Mock 'test mock' received unexpected message :not_expected with (:foo, :bar)"
73
+ end
74
+
75
+ it "should use block for expectation if provided" do
76
+ @mock.should_receive(:expected_message) do |a, b|
77
+ a.should == :first
78
+ b.should == :second
79
+ 'foo'
80
+ end
81
+
82
+ @mock.expected_message(:first, :second).should == 'foo'
83
+
84
+ verify_mock
85
+ end
86
+
87
+ it "should use block with given arguments for expectation if provided" do
88
+ @mock.should_receive(:expected_message).with(:expected_arg) do |arg|
89
+ arg.should == :expected_arg
90
+ 'foo'
91
+ end
92
+
93
+ @mock.expected_message(:expected_arg).should == 'foo'
94
+
95
+ verify_mock
96
+ end
97
+
98
+ it "should raise a MockExpectationError if block for expectation fails" do
99
+ @mock.should_receive(:expected_message) do |arg|
100
+ arg.should == :expected_arg
101
+ end
102
+
103
+ lambda {
104
+ @mock.expected_message(:unexpected_arg)
105
+ }.should.raise(Facon::MockExpectationError).message.should == "Mock 'test mock' received :expected_message but passed block failed with: :unexpected_arg.==(:expected_arg) failed"
106
+ end
107
+
108
+ it "should raise a MockExpectationError if there's a block for expectation and an #and_return expectation is also set" do
109
+ lambda {
110
+ @mock.should_receive(:foo) do
111
+ :this
112
+ end.and_return(:that)
113
+ }.should.raise(Facon::MockExpectationError).message.should == 'Ambiguous return expectation'
114
+ end
115
+
116
+ it "should pass when receiving a message the expected number of times" do
117
+ @mock.should_receive(:message).times(3)
118
+
119
+ 3.times do
120
+ @mock.message
121
+ end
122
+
123
+ verify_mock
124
+ end
125
+
126
+ it "should raise a MockExpectationError when receiving a message < expected number of times" do
127
+ @mock.should_receive(:message).times(3)
128
+
129
+ 1.times do
130
+ @mock.message
131
+ end
132
+
133
+ lambda { @mock.spec_verify }.should.raise(Facon::MockExpectationError).message.should == "Mock 'test mock' expected :message with (any args) 3 times, but received it 1 time"
134
+ end
135
+
136
+ it "should raise a MockExpectationError when receiving a message > expected number of times" do
137
+ @mock.should_receive(:message).times(3)
138
+
139
+ 5.times do
140
+ @mock.message
141
+ end
142
+
143
+ lambda { @mock.spec_verify }.should.raise(Facon::MockExpectationError).message.should == "Mock 'test mock' expected :message with (any args) 3 times, but received it 5 times"
144
+ end
145
+
146
+ it "should pass when receiving a message once as expected" do
147
+ @mock.should.receive(:message).once
148
+
149
+ @mock.message
150
+
151
+ verify_mock
152
+ end
153
+
154
+ it "should raise a MockExpectationError when never receiving a message but expecting it once" do
155
+ @mock.should.receive(:message).once
156
+
157
+ lambda { @mock.spec_verify }.should.raise(Facon::MockExpectationError).message.should == "Mock 'test mock' expected :message with (any args) 1 time, but received it 0 times"
158
+ end
159
+
160
+ it "should raise a MockExpectationError when receiving a message more than once but expecting it once" do
161
+ @mock.should.receive(:message).once
162
+
163
+ 2.times do
164
+ @mock.message
165
+ end
166
+
167
+ lambda { @mock.spec_verify }.should.raise(Facon::MockExpectationError).message.should == "Mock 'test mock' expected :message with (any args) 1 time, but received it 2 times"
168
+ end
169
+
170
+ it "should pass when never receiving a message as expected" do
171
+ @mock.should.receive(:message).never
172
+
173
+ verify_mock
174
+ end
175
+
176
+ it "should raise a MockExpectationError when receiving a message but never expecting it" do
177
+ @mock.should.receive(:message).never
178
+
179
+ @mock.message
180
+
181
+ lambda { @mock.spec_verify }.should.raise(Facon::MockExpectationError).message.should == "Mock 'test mock' expected :message with (any args) 0 times, but received it 1 time"
182
+ end
183
+ end
@@ -0,0 +1,20 @@
1
+ describe "Facon::Mock" do
2
+ before do
3
+ @mock = Facon::Mock.new('test mock')
4
+ end
5
+
6
+ it "should stub out a method on a mock" do
7
+ @mock.stub!(:stubbed_method).and_return(:stub_value)
8
+
9
+ @mock.stubbed_method.should == :stub_value
10
+ @mock.stubbed_method.should == :stub_value # called twice to ensure it stays
11
+ end
12
+
13
+ it "should stub out a method on a non-mock" do
14
+ non_mock = Object.new
15
+ non_mock.stub!(:stubbed_method).and_return(:stub_value)
16
+
17
+ non_mock.stubbed_method.should == :stub_value
18
+ non_mock.stubbed_method.should == :stub_value # called twice to ensure it stays
19
+ end
20
+ end
@@ -0,0 +1,125 @@
1
+ describe "A method stub" do
2
+ before do
3
+ @class = Class.new do
4
+ def self.existing_class_method
5
+ :original_value
6
+ end
7
+
8
+ def existing_instance_method
9
+ :original_value
10
+ end
11
+ end
12
+ @object = @class.new
13
+ end
14
+
15
+ it "should override existing methods" do
16
+ @object.existing_instance_method.should == :original_value
17
+ @object.stub!(:existing_instance_method).and_return(:stubbed_value)
18
+
19
+ @object.existing_instance_method.should == :stubbed_value
20
+ end
21
+
22
+ it "should return the expected value given to #and_return when the stubbed method is received" do
23
+ @object.stub!(:stubbed_method).and_return(:stubbed_value)
24
+
25
+ @object.stubbed_method.should == :stubbed_value
26
+ end
27
+
28
+ it "should ignore when the stubbed method is received" do
29
+ @object.stub!(:stubbed_method)
30
+
31
+ lambda {
32
+ @object.stubbed_method
33
+ }.should.not.raise
34
+ end
35
+
36
+ it "should ignore when the stubbed method is received with arguments" do
37
+ @object.stub!(:stubbed_method)
38
+
39
+ lambda {
40
+ @object.stubbed_method(:some_arg)
41
+ }.should.not.raise
42
+ end
43
+
44
+ it "should yield the argument given to #and_yield" do
45
+ @object.stub!(:yielding_method).and_yield(:yielded)
46
+
47
+ yielded = nil
48
+ @object.yielding_method { |arg| yielded = arg }
49
+
50
+ yielded.should == :yielded
51
+ end
52
+
53
+ it "should yield the multiple arguments given to #and_yield" do
54
+ @object.stub!(:yielding_method).and_yield(:first, :second)
55
+
56
+ first_arg, second_arg = nil, nil
57
+ @object.yielding_method { |arg1, arg2| first_arg, second_arg = arg1, arg2 }
58
+
59
+ first_arg.should == :first
60
+ second_arg.should == :second
61
+ end
62
+
63
+ it "should yield multiple times with multiple calls to #and_yield (i.e. allow chaining of #and_yield calls)" do
64
+ @object.stub!(:yielding_method).and_yield(:one).and_yield(:two)
65
+
66
+ yielded = []
67
+ @object.yielding_method { |arg| yielded << arg }
68
+
69
+ yielded.should == [:one, :two]
70
+ end
71
+
72
+ it "should be able to yield and return different objects (i.e. allow #and_yield and #and_return chaining)" do
73
+ @object.stub!(:yield_and_return).and_yield(:yielded).and_return(:returned)
74
+
75
+ yielded = nil
76
+ @object.yield_and_return { |arg| yielded = arg }.should == :returned
77
+
78
+ yielded.should == :yielded
79
+ end
80
+
81
+ it "should raise the expected exception given to #and_raise" do
82
+ @object.stub!(:failing_method).and_raise(RuntimeError)
83
+
84
+ lambda { @object.failing_method }.should.raise(RuntimeError)
85
+ end
86
+
87
+ it "should throw the expected thrown value given to #and_throw" do
88
+ @object.stub!(:pitch).and_throw(:ball)
89
+
90
+ lambda { @object.pitch }.should.throw(:ball)
91
+ end
92
+
93
+ it "should ignore when the stubbed method is never called" do
94
+ end
95
+ end
96
+
97
+ describe "A method stub with arguments" do
98
+
99
+ before do
100
+ @object = Object.new
101
+ @object.stub!(:stubbed_method).with(:expected_arg).and_return(:stubbed_value)
102
+ end
103
+
104
+ it "should ignore when never called" do
105
+ end
106
+
107
+ it "should ignore when called with expected argument" do
108
+ @object.stubbed_method(:expected_arg)
109
+ end
110
+
111
+ it "should raise a NoMethodError when called with no arguments" do
112
+ lambda { @object.stubbed_method }.should.raise(NoMethodError)
113
+ end
114
+
115
+ it "should raise a NoMethodError when called with some other argument" do
116
+ lambda { @object.stubbed_method(:something_else) }.should.raise(NoMethodError)
117
+ end
118
+
119
+ it "should allow another stub with different arguments" do
120
+ @object.stub!(:stubbed_method).with(:something_else).and_return(:bar)
121
+
122
+ @object.stubbed_method(:expected_arg).should == :stubbed_value
123
+ @object.stubbed_method(:something_else).should == :bar
124
+ end
125
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: motion-facon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - chuyeow
9
+ - svyatogor
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-04-11 00:00:00.000000000 Z
14
+ dependencies: []
15
+ description: Port of facon mocking library to rubymotion.
16
+ email:
17
+ - chuyeow@gmail.com
18
+ - svyatogor@gmail.com
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - .gitignore
24
+ - Changelog.txt
25
+ - Gemfile
26
+ - Gemfile.lock
27
+ - README.md
28
+ - Rakefile
29
+ - app/app_delegate.rb
30
+ - lib/motion-facon.rb
31
+ - lib/motion-facon/baconize.rb
32
+ - lib/motion-facon/error_generator.rb
33
+ - lib/motion-facon/expectation.rb
34
+ - lib/motion-facon/mock.rb
35
+ - lib/motion-facon/mockable.rb
36
+ - lib/motion-facon/proxy.rb
37
+ - lib/motion-facon/spec_helpers.rb
38
+ - lib/motion-facon/version.rb
39
+ - motion-facon.gemspec
40
+ - resources/Default-568h@2x.png
41
+ - spec/baconize_spec.rb
42
+ - spec/expectation_spec.rb
43
+ - spec/mock_spec.rb
44
+ - spec/stub_spec.rb
45
+ homepage: https://github.com/svyatogor/motion-facon
46
+ licenses: []
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ none: false
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ none: false
63
+ requirements: []
64
+ rubyforge_project: motion-facon
65
+ rubygems_version: 1.8.24
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Tiny mocking library.
69
+ test_files:
70
+ - app/app_delegate.rb
71
+ - spec/baconize_spec.rb
72
+ - spec/expectation_spec.rb
73
+ - spec/mock_spec.rb
74
+ - spec/stub_spec.rb