Creates a test double representing string_or_model_class with common ActiveModel methods stubbed out. Additional methods may be easily stubbed (via add_stubs) if stubs is passed. This is most useful for impersonating models that don’t exist yet.
NOTE that only ActiveModel’s methods, plus new_record?, are stubbed out implicitly. new_record? returns the inverse of persisted?, and is present only for compatibility with extension frameworks that have yet to update themselves to the ActiveModel API (which declares persisted?, not new_record?).
string_or_model_class can be any of:
* A String representing a Class that does not exist * A String representing a Class that extends ActiveModel::Naming * A Class that extends ActiveModel::Naming
# File lib/rspec/rails/mocks.rb, line 59 def mock_model(string_or_model_class, stubs = {}) if String === string_or_model_class if Object.const_defined?(string_or_model_class) model_class = Object.const_get(string_or_model_class) else model_class = Object.const_set(string_or_model_class, Class.new do extend ActiveModel::Naming end) end else model_class = string_or_model_class end unless model_class.kind_of? ActiveModel::Naming raise ArgumentError.new The mock_model method can only accept as its first argument: * A String representing a Class that does not exist * A String representing a Class that extends ActiveModel::Naming * A Class that extends ActiveModel::NamingIt received #{model_class.inspect} end stubs = stubs.reverse_merge(:id => next_id) stubs = stubs.reverse_merge(:persisted? => !!stubs[:id]) stubs = stubs.reverse_merge(:destroyed? => false) stubs = stubs.reverse_merge(:marked_for_destruction? => false) stubs = stubs.reverse_merge(:blank? => false) mock("#{model_class.name}_#{stubs[:id]}", stubs).tap do |m| m.extend ActiveModelInstanceMethods m.singleton_class.__send__ :include, ActiveModel::Conversion m.singleton_class.__send__ :include, ActiveModel::Validations if defined?(ActiveRecord) m.extend ActiveRecordInstanceMethods [:save, :update_attributes].each do |key| if stubs[key] == false m.errors.stub(:empty?) { false } end end end m.__send__(:__mock_proxy).instance_eval( def @object.is_a?(other) #{model_class}.ancestors.include?(other) end def @object.kind_of?(other) #{model_class}.ancestors.include?(other) end def @object.instance_of?(other) other == #{model_class} end def @object.respond_to?(method_name, include_private=false) #{model_class}.respond_to?(:column_names) && #{model_class}.column_names.include?(method_name.to_s) || super end def @object.class #{model_class} end def @object.to_s "#{model_class.name}_#{to_param}" end, __FILE__, __LINE__) yield m if block_given? end end
Creates an instance of Model with to_param stubbed using a generated value that is unique to each object.. If Model is an ActiveRecord model, it 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.
persisted? is overridden to return the result of !id.nil? This means that by default persisted? will return true. 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 persisted? will return false, 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.
stub_model(Person) stub_model(Person).as_new_record stub_model(Person, :to_param => 37) stub_model(Person) do |person| person.first_name = "David" end
# File lib/rspec/rails/mocks.rb, line 187 def stub_model(model_class, stubs={}) model_class.new.tap do |m| m.extend ActiveModelStubExtensions if defined?(ActiveRecord) && model_class < ActiveRecord::Base m.extend ActiveRecordStubExtensions primary_key = model_class.primary_key.to_sym stubs = stubs.reverse_merge(primary_key => next_id) stubs = stubs.reverse_merge(:persisted? => !!stubs[primary_key]) else stubs = stubs.reverse_merge(:id => next_id) stubs = stubs.reverse_merge(:persisted? => !!stubs[:id]) end stubs = stubs.reverse_merge(:blank? => false) stubs.each do |k,v| m.__send__("#{k}=", stubs.delete(k)) if m.respond_to?("#{k}=") end m.stub(stubs) yield m if block_given? end end
Generated with the Darkfish Rdoc Generator 2.