tracks/vendor/plugins/rspec-rails/lib/spec/rails/mocks.rb
Luke Melia 35ae5fc431 Next step in upgrading Tracks to Rails 2.2. Some highlights:
* 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
2008-11-30 00:34:15 -05:00

132 lines
4.6 KiB
Ruby

module Spec
module Rails
class IllegalDataAccessException < StandardError; end
module Mocks
# Creates a mock object instance for a +model_class+ with common
# methods stubbed out. Additional methods may be easily stubbed (via
# add_stubs) if +stubs+ is passed.
def mock_model(model_class, options_and_stubs = {})
id = options_and_stubs[:id] || next_id
options_and_stubs = options_and_stubs.reverse_merge({
:id => id,
:to_param => id.to_s,
:new_record? => false,
:errors => stub("errors", :count => 0)
})
m = mock("#{model_class.name}_#{id}", options_and_stubs)
m.send(:__mock_proxy).instance_eval <<-CODE
def @target.as_new_record
self.stub!(:id).and_return nil
self.stub!(:to_param).and_return nil
self.stub!(:new_record?).and_return true
self
end
def @target.is_a?(other)
#{model_class}.ancestors.include?(other)
end
def @target.kind_of?(other)
#{model_class}.ancestors.include?(other)
end
def @target.instance_of?(other)
other == #{model_class}
end
def @target.class
#{model_class}
end
CODE
yield m if block_given?
m
end
module ModelStubber
def connection
raise Spec::Rails::IllegalDataAccessException.new("stubbed models are not allowed to access the database")
end
def new_record?
id.nil?
end
def as_new_record
self.id = nil
self
end
end
# :call-seq:
# stub_model(Model)
# stub_model(Model).as_new_record
# stub_model(Model, hash_of_stubs)
# stub_model(Model, instance_variable_name, hash_of_stubs)
#
# Creates an instance of +Model+ that is prohibited from accessing the
# database*. For each key in +hash_of_stubs+, if the model has a
# matching attribute (determined by asking it) are simply assigned the
# submitted values. If the model does not have a matching attribute, the
# key/value pair is assigned as a stub return value using RSpec's
# mocking/stubbing framework.
#
# <tt>new_record?</tt> is overridden to return the result of id.nil?
# This means that by default new_record? will return false. If you want
# the object to behave as a new record, sending it +as_new_record+ will
# set the id to nil. You can also explicitly set :id => nil, in which
# case new_record? will return true, but using +as_new_record+ makes the
# example a bit more descriptive.
#
# While you can use stub_model in any example (model, view, controller,
# helper), it is especially useful in view examples, which are
# inherently more state-based than interaction-based.
#
# == Database Independence
#
# +stub_model+ does not make your examples entirely
# database-independent. It does not stop the model class itself from
# loading up its columns from the database. It just prevents data access
# from the object itself. To completely decouple from the database, take
# a look at libraries like unit_record or NullDB.
#
# == Examples
#
# stub_model(Person)
# stub_model(Person).as_new_record
# stub_model(Person, :id => 37)
# stub_model(Person) do |person|
# person.first_name = "David"
# end
def stub_model(model_class, stubs={})
stubs = {:id => next_id}.merge(stubs)
returning model_class.new do |model|
model.id = stubs.delete(:id)
model.extend ModelStubber
stubs.each do |k,v|
if model.has_attribute?(k)
model[k] = stubs.delete(k)
end
end
add_stubs(model, stubs)
yield model if block_given?
end
end
#--
# TODO - Shouldn't this just be an extension of stub! ??
# - object.stub!(:method => return_value, :method2 => return_value2, :etc => etc)
#++
# Stubs methods on +object+ (if +object+ is a symbol or string a new mock
# with that name will be created). +stubs+ is a Hash of +method=>value+
def add_stubs(object, stubs = {}) #:nodoc:
m = [String, Symbol].index(object.class) ? mock(object.to_s) : object
stubs.each {|k,v| m.stub!(k).and_return(v)}
m
end
private
@@model_id = 1000
def next_id
@@model_id += 1
end
end
end
end