[rspec-devel] huge setup methods? I think I'm on the wrong path

Matt Pelletier matt at eastmedia.com
Thu Jan 25 22:29:41 EST 2007


On Jan 25, 2007, at 1:57 AM, Jens-Christian Fischer wrote:

>>
>> The following code can be crammed into spec_helper.rb inside
>> EvalContext. I wrote it here just wrapped in a class_eval. Wilson
>> originally posted mock_model on his blog (http://metaclass.org/
>> 2006/12/22/making-a-mockery-of-activerecord). This is a slightly
>> modified version.
>>
>> Spec::Rails::class EvalContext.class_eval do
>>
>>        def mock_model(name, stubs = {})
>>          name = name.to_s
>>          m = mock(name)
>>          instance_variable_set("@#{name}", m)
>>          id = rand(10_000)
>>          m.stub!(:id).and_return(id)
>>          m.stub!(:to_param).and_return(id)
>>          m.stub!(:new_record?).and_return(false)
>>          klass = name.singularize.camelize
>>          m.send(:__mock_handler).instance_eval <<-CODE
>>            def @target.is_a?(other)
>>              other == #{klass}
>>            end
>>            def @target.class
>>              #{klass}
>>            end
>>          CODE
>>          add_stubs(m,stubs)
>>          yield m if block_given?
>>          m
>>        end
>>
>>        # Will add stubs to a new or existing object.
>>        # Passing a symbol or string will create a new mock, passing
>> anything else
>>        # will create a new mock and add stubs to that
>>        def add_stubs(object, stubs = {})
>>          m = object.class.in?([String, Symbol]) ? mock(object.to_s) :
>> object
>>          stubs.each {|k,v| m.stub!(k).and_return(v)}
>>          m
>>        end
>> end
>
>
> Was playing around with this... It breaks on Rails 1.2.1 with a
>
> Anonymous modules have no name to be referenced by
> (eval):5:in `class'
> ./spec/views/users/../../spec_helper.rb:68:in `add_stubs'
> ./spec/views/users/../../spec_helper.rb:40:in `mock_model'
> ./spec/views/users/show_view_spec.rb:12:
>
>
> error. I have traced that to
>
> /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/
> active_support/dependencies.rb in the to_contant_name method. My Ruby-
> Fu sadly lacks, so I haven't been able to figure out a cure to this
> problem. Using the block form:
>
>      mock_model :u1 do |m|
>        m.stub!(:nickname).and_return("jcfischer")
>        m.stub!(:rooms).and_return(rooms)
>      end
>
> works fine

Did you figure it out or is it still causing problems? I realized  
that in add_stubs I am calling a method that I always use in my  
projects (sugar for #include?):

You can either add this to your project, like so:

# from Technoblog
# http://tech.rufy.com/entry/81
class Object
   def in?(collection)
     collection.respond_to?(:include?) ? collection.include?(self) :  
false
   end
end

or, if Aslak is adding this to the RSpec Rails plugin, just change  
add_stub to use #include?. Here is an updated version of both methods  
(I just cleaned up mock_model so it would allow you to override the  
default stubs):

       # Adds stubs on a new or existing object. A new mock will be  
created if the
       # first param is a Symbol or String.
       def add_stubs(object, stubs = {})
         m = [String, Symbol].include?(object.class) ? mock 
(object.to_s) : object
         stubs.each {|k,v| m.stub!(k).and_return(v)}
         m
       end

       # Creates a mock for an ActiveRecord model and places it in an  
instance variable.
       # Automatically creates stubs for commonly called methods such  
as #id, #to_param,
       # and #new_record?. You can pass a hash of stubs you would  
like created (these
       # will override the defaults). It also accepts an optional block.
       def mock_model(name, stubs = {})
         name = name.to_s
         m = mock(name)
         instance_variable_set("@#{name}", m)
         id = stubs[:id] || rand(10_000)
         stubs.reverse_merge! :id => id, :to_param =>  
id, :new_record? => false
         klass = name.singularize.camelize
         m.send(:__mock_handler).instance_eval <<-CODE
           def @target.is_a?(other)
             other == #{klass}
           end
           def @target.class
             #{klass}
           end
         CODE
         add_stubs(m,stubs)
         yield m if block_given?
         m
       end


Thanks,
Matt


>
> Any ideas?
> jc
> _______________________________________________
> rspec-devel mailing list
> rspec-devel at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-devel

------------------
Matt Pelletier
http://www.eastmedia.com -- EastMedia
http://www.informit.com/title/0321483502 -- The Mongrel Book
http://identity.eastmedia.com -- OpenID, Identity 2.0





More information about the rspec-devel mailing list