GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Description: helper plugin for Rspec controller specs when using make_resourceful
Clone URL: git://github.com/adzap/mock_resourceful.git
name age message
file .gitignore Wed Jun 11 05:17:34 -0700 2008 added ignore file [adzap]
file CHANGELOG Tue Sep 30 01:25:52 -0700 2008 adding changelog with failure flag changes [adzap]
file MIT-LICENSE Sat Jun 14 02:37:51 -0700 2008 first commit [adzap]
file README Tue Sep 30 00:59:55 -0700 2008 improving on the silly failure flags I had impl... [adzap]
file Rakefile Tue Sep 30 01:01:48 -0700 2008 removed test/unit stuff and made spec the defau... [adzap]
file init.rb Wed Aug 06 22:31:58 -0700 2008 needed to load spec/rails before including mock... [adzap]
directory lib/ Tue Sep 30 00:59:55 -0700 2008 improving on the silly failure flags I had impl... [adzap]
directory spec/ Tue Sep 30 00:59:55 -0700 2008 improving on the silly failure flags I had impl... [adzap]
README
MockResourceful
===============

If you are using make_resourceful and like to avoid database overhead in your
controller specs, then it is likely that your specs have an amount of mock and 
stub bloat to control the objects returned for test requests in a 
make_resourceful controller.

This plugin makes it simpler and cleaner to control object creation with mocks
for controller specs when using make_resourceful. It does this while not hiding
any of the important behaviour of the controller being tested. 


Example
=======

Say you have a controller using make_resourceful:

  class ThingsController < ActionController:Base
    make_resourceful do
      actions :all
    end
  end

And in your spec you want to test its behaviour but avoid database hits by using
mocks and stubs. You just do the following:

  describe ThingsController do
    mock_resourceful
    
    describe "GET /things/new" do
      before do
        do_new
      end
      
      it "should assign a thing instance" do
        assigns[:thing].should_not be_nil
      end
    end
  end

The Thing object assigned will be a mock of the Thing class using Rspecs 
mock_model method. The do_new method performs a 'get :new' request as well
specific setup for a new action, such as stubbing the new method to return
a mock object which has the new_record? method stubbed to return true.

This a simple example but the plugin will handle the nested resources, request
failure and object serialization while not touching the database or hiding 
controller implementation.

Setup
=====

To start using it, just install and its ready to go. To use it in your controller
spec, add 'mock_resourceful' to the top of the controller describe block like so

  describe ThingsController do
    mock_resourceful
    ...

Usage
=====

When specing a controllers response to a request, use the appropriate plugin 
request method to setup the correct mocking and stubbing based on the request 
action, parameters and default make_resourceful behaviour.

The plugin tries to mock and stub only the bare minimum of the make_resourceful
methods to avoid hiding any controller behaviour which needs testing. 


== Request Methods

All default RESTful actions have an equivalent request method. These are 
  - do_index
  - do_new
  - do_create
  - do_edit
  - do_udpate
  - do_show
  - do_delete

and for custom actions

  - do_action :custom_action_name, :get # action name and HTTP method
  
All methods take a optional params hash. For singular actions (i.e. not a 
collection) the :id key is set to the id of the mock model object by default. 
For do_create and do_update an empty hash with the model name as the key to
simulate the form params being submitted.

Each request can also take a failure option in the params hash to simulate 
request failures as the first parameter. See Test Failed Requests below.


== Request Class Methods

A more concise way to use the request methods is to use the class method version
of each do_ action method. For example:

  describe ThingsController do
    mock_resourceful
    
    describe "GET /things/new" do
      do_new
      
      it "should assign a thing instance" do
        assigns[:thing].should_not be_nil
      end            
    end
  end

Using the class methods necessitates that you nest your describe blocks for 
examples pertaining to the same request and parameters.

You can also pass a block to the class request methods which is executed before
the request to do request specific customized setup like mock object 
expectations or stubs. 

  describe ThingsController do
    mock_resourceful
    
    describe "GET /things/new" do
      do_new do
        model_object.should_receive(:other_method).and_return('stuff')
      end
      
      it "should assign a thing instance" do
        assigns[:thing].should_not be_nil
      end            
    end
  end

Any controller wide mock object setup should be done by overriding the object
creation methods. See Customize Mock Objects.


== Helper Methods

In the previous example the 'model_object' method was used. This is a helper 
method which returns the mock object created for the controller. You can use
this method to customize the object before the request or refer to it in your 
examples such as testing redirects like this

  it "should redirect to show" do
    response.should redirect_to thing_path(model_object)
  end

The available helper methods are:

 * model_object  - the mock model object
 * collection    - the mock collection object
 * parent_object - the parent_object, which is only created if 
                   request includes parent id
 * parent        - name of the parent used for the request


== Collection Object

When doing a do_index, the collection object instance is created as an array
with the mocked model object in it.

  describe ThingsController do
    mock_resourceful
    
    describe "GET /things" do
      do_index
      
      it "should assign a things instance" do
        assigns[:things].should == [ model_object ]
      end
    end
  end

You can override the collection object creation to return what ever you need.
See Customize Mock Objects.


== Nested Resources

If your RESTful controller is a nested resource and you have used the belongs_to
in the make_resourceful block such as 

  class ThingsController < ActionController:Base
    make_resourceful do
      actions :all
      belongs_to :thing_parent
    end
  end

  class ThingParentsController < ActionController:Base
    make_resourceful do
      actions :all
    end
  end

then the parent object will be created automatically if the request params 
contains the parent id like so

  describe ThingsController do
    mock_resourceful
    
    describe "GET /thing_parents/1/things/new" do
      do_new :thing_parent_id => 1
      
      it "should assign a thing parent instance" do
        assigns[:thing_parent].should_not be_nil
      end            
    end
  end

The model object is stubbed to return the parent using the association method.

== Customize Mock Objects

You can control the mock object creation by overidding the create_model_object,
create_collection_object and create_parent_object methods in the describe block.
The methods take the model as an argument. Like so

  describe ThingsController do
    mock_resourceful
    
    describe "GET /things/new" do
      do_new
      
      it "should assign a thing instance" do
        assigns[:thing].should_not be_nil
      end            
    end
    
    # single model object
    def create_model_object(model)
      mock_model(model, :says => 'return of the mock')
    end
    
    # for index action
    def create_collection_object(model)
      [mock_model(model, :says => 'what do you call a group of mocks?')]
    end
    
    # used if request params has parent id key
    def create_parent_object(model)
      mock_model(model, :says => 'go to your room!')
    end  
  end

If your object creation was generalizable to all the controller specs, you could 
define these in a module to be included in the spec runner.


== Test Failed Requests

To test the behaviour of the controller actions when there is failure, you pass 
in the :fail_on option in the params to indicate which failure you want
to occur.

The action request methods with their valid failure options are:

  do_create 
   - :fail_on => :save

  do_edit 
   - :fail_on => :find

  do_update 
   - :fail_on => :find
   - :fail_on => :update

  do_show 
   - :fail_on => :update
  
  do_delete 
   - :fail_on => :find
   - :fail_on => :destroy

Passing in these failure options will stub the appropriate return values on the objects to
indicate a failure to the make_resourceful controller.


== Object Serialization

By default the return value for any serialization to XML or other formats is
the string value of the format passed to the object serialize method by 
make_resourceful. To override this define the following methods in the describe 
block, like so

  def serialize_model_object(format, options)
    case format
      when :xml  then 'XML'
      when :json then 'JSON'
      else            format.to_s.upcase
    end
  end
  
  def serialize_collection(format, options)
    case format
      when :xml  then 'XML'
      when :json then 'JSON'
      else            format.to_s.upcase
    end
  end

The case statements are optional and included to demonstrate per format handling.


Details
=======

Author: Adam Meehan (adam.meehan at gmail.com)

Source:  http://github.com/adzap/mock_resourceful
Tickets: http://adzap.lighthouseapp.com/projects/12968-mock_resourceful

License
=======

Copyright (c) 2008 Adam Meehan, released under the MIT license