[mocha-developer] Login systems : stubbing accounts and AR association proxies

Zack Chandler zackchandler at gmail.com
Tue Feb 6 10:43:51 EST 2007


On 2/6/07, Jonathan del Strother <maillist at steelskies.com> wrote:
> My Rails site has a fair amount of login and 'ownership' logic.  For
> instance, we have a number of clients (companies), each of which has
> several accounts.  A client owns a number of different types of
> resources, and shouldn't see any other clients' resources, so, for
> example, our ScenesController contains a lot of references to
> 'current_client.scenes', rather than Scene.find(:all)
>
>
> All of which works pretty well, but it can make testing very
> tedious.  I always need to set up a fake client, and a fake account,
> and log in with that account, and make sure that whatever resource
> I'm dealing with in that unit test is assigned to the fake client,
> and so on.
> I'm starting to wonder whether I ought to stub all the login and
> ownership logic out of my functional tests, so I can concentrate on
> whatever resource I'm dealing with in that given test.  All the login/
> ownership stuff could be handled in integration testing, which is
> probably better suited to it anyway, due to having real sessions etc
> etc.
>
> I'm having difficulty doing so, however.  The controller uses some
> current_account / current_client methods to find whoever's logged in
> - stubbing those to return a fake client/account is easy, but you're
> then left with problems with Rails' association proxies.  There's
> lots of use of things like  current_client.scenes.build, which are
> not so easy to stub out (particularly as, AFAICT, you can't make use
> of any arguments passed into a stubbed method).
>
>
> Has anyone else done anything similar, or am I just creating more
> work for myself by trying to remove login details from functional
> testing?
>
>
> Jon

I've noticed too that association proxies are hard to mock up.  Here's
an example of how I have done it:

In your controller:

  def some_action
    @tasks = current_user.tasks.find(:all, :conditions => [...])
  end

In your functional test:

User.any_instance.stubs(:tasks).returns(Task)
Task.stubs(:find).returns([Task.new(...), Task.new(...)])

I would think their is a better way.  For one thing this hard-codes
the return values up so any call with any conditions would return the
same array of tasks.

Still it is super-simple and works in common cases.

I'd be interested to hear about better ways to do this.

--
Zack Chandler
http://depixelate.com


More information about the mocha-developer mailing list