mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-26 12:08:47 +01:00
* Ran rake rails:update * Added old actionwebservice framework * Updated RSpec and RSpec-Rails * Removed asset_packager plugin (not compatible, Scott no longer maintaining), and replaced with bundle_fu. See the bundle_fu README for more info. * Hacks to UJS and ARTS plugins, which are no longer supported. Probably should move off both UJS and RJS. * Hack to flashobject_helper plugin (upgrade to Rails 2.2-compatible version if/when it comes out.) * Hack to skinny-spec plugin, for Rails 2.2 compatibility. Should check for official release. * Hacks to resource_feeder plugin, for Rails 2.2 compatibility. Should check for official release (not likely) or move off it. * Addressed some deprecation warnings. More to come. * My mobile mime type hackery is no longer necessary with new Rails features. Yay! * Updated environment.rb.tmpl with changes TODO: * Restore view specs marked pending * Fix failing integration tests. * Try selenium tests. * Investigate OpenID support. * Address deprecation warnings. * Consider moving parts of environment.rb to initializers * Address annoying config.gem warning about highline gem
224 lines
6.8 KiB
Ruby
224 lines
6.8 KiB
Ruby
module Spec
|
|
module Mocks
|
|
class Proxy
|
|
DEFAULT_OPTIONS = {
|
|
:null_object => false,
|
|
}
|
|
|
|
@@warn_about_expectations_on_nil = true
|
|
|
|
def self.allow_message_expectations_on_nil
|
|
@@warn_about_expectations_on_nil = false
|
|
|
|
# ensure nil.rspec_verify is called even if an expectation is not set in the example
|
|
# otherwise the allowance would effect subsequent examples
|
|
$rspec_mocks.add(nil) unless $rspec_mocks.nil?
|
|
end
|
|
|
|
def initialize(target, name=nil, options={})
|
|
@target = target
|
|
@name = name
|
|
@error_generator = ErrorGenerator.new target, name
|
|
@expectation_ordering = OrderGroup.new @error_generator
|
|
@expectations = []
|
|
@messages_received = []
|
|
@stubs = []
|
|
@proxied_methods = []
|
|
@options = options ? DEFAULT_OPTIONS.dup.merge(options) : DEFAULT_OPTIONS
|
|
end
|
|
|
|
def null_object?
|
|
@options[:null_object]
|
|
end
|
|
|
|
def as_null_object
|
|
@options[:null_object] = true
|
|
@target
|
|
end
|
|
|
|
def add_message_expectation(expected_from, sym, opts={}, &block)
|
|
__add sym
|
|
warn_if_nil_class sym
|
|
if existing_stub = @stubs.detect {|s| s.sym == sym }
|
|
expectation = existing_stub.build_child(expected_from, block_given?? block : nil, 1, opts)
|
|
else
|
|
expectation = MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil, 1, opts)
|
|
end
|
|
@expectations << expectation
|
|
@expectations.last
|
|
end
|
|
|
|
def add_negative_message_expectation(expected_from, sym, &block)
|
|
__add sym
|
|
warn_if_nil_class sym
|
|
@expectations << NegativeMessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil)
|
|
@expectations.last
|
|
end
|
|
|
|
def add_stub(expected_from, sym, opts={})
|
|
__add sym
|
|
@stubs.unshift MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, nil, :any, opts)
|
|
@stubs.first
|
|
end
|
|
|
|
def verify #:nodoc:
|
|
verify_expectations
|
|
ensure
|
|
reset
|
|
end
|
|
|
|
def reset
|
|
clear_expectations
|
|
clear_stubs
|
|
reset_proxied_methods
|
|
clear_proxied_methods
|
|
reset_nil_expectations_warning
|
|
end
|
|
|
|
def received_message?(sym, *args, &block)
|
|
@messages_received.any? {|array| array == [sym, args, block]}
|
|
end
|
|
|
|
def has_negative_expectation?(sym)
|
|
@expectations.detect {|expectation| expectation.negative_expectation_for?(sym)}
|
|
end
|
|
|
|
def message_received(sym, *args, &block)
|
|
expectation = find_matching_expectation(sym, *args)
|
|
stub = find_matching_method_stub(sym, *args)
|
|
|
|
if (stub && expectation && expectation.called_max_times?) || (stub && !expectation)
|
|
if expectation = find_almost_matching_expectation(sym, *args)
|
|
expectation.advise(args, block) unless expectation.expected_messages_received?
|
|
end
|
|
stub.invoke([], block)
|
|
elsif expectation
|
|
expectation.invoke(args, block)
|
|
elsif expectation = find_almost_matching_expectation(sym, *args)
|
|
expectation.advise(args, block) if null_object? unless expectation.expected_messages_received?
|
|
raise_unexpected_message_args_error(expectation, *args) unless (has_negative_expectation?(sym) or null_object?)
|
|
else
|
|
@target.send :method_missing, sym, *args, &block
|
|
end
|
|
end
|
|
|
|
def raise_unexpected_message_args_error(expectation, *args)
|
|
@error_generator.raise_unexpected_message_args_error expectation, *args
|
|
end
|
|
|
|
def raise_unexpected_message_error(sym, *args)
|
|
@error_generator.raise_unexpected_message_error sym, *args
|
|
end
|
|
|
|
private
|
|
|
|
def __add(sym)
|
|
$rspec_mocks.add(@target) unless $rspec_mocks.nil?
|
|
define_expected_method(sym)
|
|
end
|
|
|
|
def warn_if_nil_class(sym)
|
|
if proxy_for_nil_class? && @@warn_about_expectations_on_nil
|
|
Kernel.warn("An expectation of :#{sym} was set on nil. Called from #{caller[2]}. Use allow_message_expectations_on_nil to disable warnings.")
|
|
end
|
|
end
|
|
|
|
def define_expected_method(sym)
|
|
visibility_string = "#{visibility(sym)} :#{sym}"
|
|
if target_responds_to?(sym) && !target_metaclass.method_defined?(munge(sym))
|
|
munged_sym = munge(sym)
|
|
target_metaclass.instance_eval do
|
|
alias_method munged_sym, sym if method_defined?(sym.to_s)
|
|
end
|
|
@proxied_methods << sym
|
|
end
|
|
|
|
target_metaclass.class_eval(<<-EOF, __FILE__, __LINE__)
|
|
def #{sym}(*args, &block)
|
|
__mock_proxy.message_received :#{sym}, *args, &block
|
|
end
|
|
#{visibility_string}
|
|
EOF
|
|
end
|
|
|
|
def target_responds_to?(sym)
|
|
return @target.send(munge(:respond_to?),sym) if @already_proxied_respond_to
|
|
return @already_proxied_respond_to = true if sym == :respond_to?
|
|
return @target.respond_to?(sym)
|
|
end
|
|
|
|
def visibility(sym)
|
|
if Mock === @target
|
|
'public'
|
|
elsif target_metaclass.private_method_defined?(sym)
|
|
'private'
|
|
elsif target_metaclass.protected_method_defined?(sym)
|
|
'protected'
|
|
else
|
|
'public'
|
|
end
|
|
end
|
|
|
|
def munge(sym)
|
|
"proxied_by_rspec__#{sym.to_s}".to_sym
|
|
end
|
|
|
|
def clear_expectations
|
|
@expectations.clear
|
|
end
|
|
|
|
def clear_stubs
|
|
@stubs.clear
|
|
end
|
|
|
|
def clear_proxied_methods
|
|
@proxied_methods.clear
|
|
end
|
|
|
|
def target_metaclass
|
|
class << @target; self; end
|
|
end
|
|
|
|
def verify_expectations
|
|
@expectations.each do |expectation|
|
|
expectation.verify_messages_received
|
|
end
|
|
end
|
|
|
|
def reset_proxied_methods
|
|
@proxied_methods.each do |sym|
|
|
munged_sym = munge(sym)
|
|
target_metaclass.instance_eval do
|
|
if method_defined?(munged_sym.to_s)
|
|
alias_method sym, munged_sym
|
|
undef_method munged_sym
|
|
else
|
|
undef_method sym
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def proxy_for_nil_class?
|
|
@target.nil?
|
|
end
|
|
|
|
def reset_nil_expectations_warning
|
|
@@warn_about_expectations_on_nil = true if proxy_for_nil_class?
|
|
end
|
|
|
|
def find_matching_expectation(sym, *args)
|
|
@expectations.find {|expectation| expectation.matches(sym, args)}
|
|
end
|
|
|
|
def find_almost_matching_expectation(sym, *args)
|
|
@expectations.find {|expectation| expectation.matches_name_but_not_args(sym, args)}
|
|
end
|
|
|
|
def find_matching_method_stub(sym, *args)
|
|
@stubs.find {|stub| stub.matches(sym, args)}
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|