motion-facon 0.5.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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