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.
- data/.gitignore +19 -0
- data/Changelog.txt +32 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +16 -0
- data/README.md +94 -0
- data/Rakefile +13 -0
- data/app/app_delegate.rb +5 -0
- data/lib/motion-facon.rb +31 -0
- data/lib/motion-facon/baconize.rb +96 -0
- data/lib/motion-facon/error_generator.rb +42 -0
- data/lib/motion-facon/expectation.rb +143 -0
- data/lib/motion-facon/mock.rb +39 -0
- data/lib/motion-facon/mockable.rb +43 -0
- data/lib/motion-facon/proxy.rb +132 -0
- data/lib/motion-facon/spec_helpers.rb +9 -0
- data/lib/motion-facon/version.rb +3 -0
- data/motion-facon.gemspec +19 -0
- data/spec/baconize_spec.rb +35 -0
- data/spec/expectation_spec.rb +183 -0
- data/spec/mock_spec.rb +20 -0
- data/spec/stub_spec.rb +125 -0
- metadata +74 -0
data/.gitignore
ADDED
@@ -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
|
data/Changelog.txt
ADDED
@@ -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
data/Gemfile.lock
ADDED
data/README.md
ADDED
@@ -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.
|
data/Rakefile
ADDED
@@ -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
|
data/app/app_delegate.rb
ADDED
data/lib/motion-facon.rb
ADDED
@@ -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,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
|
data/spec/mock_spec.rb
ADDED
@@ -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
|
data/spec/stub_spec.rb
ADDED
@@ -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
|