Testing controllers after an hexagonal refactoring

152 views
Skip to first unread message

Rafael George

unread,
Jan 8, 2014, 1:06:06 PM1/8/14
to objects-...@googlegroups.com
Hi guys, 

I was working on a code base today and I notice that after refactoring to an hexagonal Rails and moving the testing code to an isolated test for the service in question the controller left with a lot of duplicated logic in there. After removing some of that I notice that the reminder #on_failure and #on_success method are left alone without any practical tests on it. Do you guys know any good way to test this behavior ?

Thanks in advance,

Mike Kelly

unread,
Jan 8, 2014, 1:20:42 PM1/8/14
to objects-...@googlegroups.com

Hey Rafael,

Stick the callback methods in SimpleDelegator, wrap the controller in it and pass that to your service object, test the delegator in isolation by making it wrap a mock and verifying each callback method makes the expected  ActionController API calls.

Cheers,
M

--
You received this message because you are subscribed to the Google Groups "Objects on Rails" group.
To unsubscribe from this group and stop receiving emails from it, send an email to objects-on-rai...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Sam Livingston-Gray

unread,
Jan 8, 2014, 2:30:53 PM1/8/14
to objects-...@googlegroups.com
Quick note:  SimpleDelegator can have performance implications.  Every time you instantiate one, it defines new singleton methods on the instance (which, in turn, blows the method cache).  Probably fine for wrapping a controller, but I was quite surprised when a coworker discovered that a significant performance problem was being caused by creating lots of SimpleDelegator instances in an inner loop.  :D

Defining a specific Delegator subclass for the wrapped object, or just skipping the 'delegate' library altogether and using method_missing, should help.

-Sam

Jim Gay

unread,
Jan 8, 2014, 2:43:57 PM1/8/14
to objects-...@googlegroups.com
On Wed, Jan 8, 2014 at 2:30 PM, Sam Livingston-Gray <gee...@gmail.com> wrote:
> Quick note: SimpleDelegator can have performance implications. Every time
> you instantiate one, it defines new singleton methods on the instance
> (which, in turn, blows the method cache). Probably fine for wrapping a
> controller, but I was quite surprised when a coworker discovered that a
> significant performance problem was being caused by creating lots of
> SimpleDelegator instances in an inner loop. :D
>
> Defining a specific Delegator subclass for the wrapped object, or just
> skipping the 'delegate' library altogether and using method_missing, should
> help.
>
> -Sam

Where in the SimpleDelegator code does it define new singleton methods
on the instance?

According to everything I've read in the code, when you initialize a
SimpleDelegator object, it just calls __setobj__ with the provided
argument from the constructor and stores it as an instance variable.
As far as I can tell, all of those methods are defined when the
*class* is initialized.
Write intention revealing code #=> http://www.clean-ruby.com

Jim Gay
Saturn Flyer LLC
571-403-0338

Sam Livingston-Gray

unread,
Jan 8, 2014, 3:06:55 PM1/8/14
to objects-...@googlegroups.com
Whoops—that was in a Ruby 1.8.7 app.  In the 1.8.7 standard lib, the exciting bits are in Delegator#initialize.  Looks like this was cleaned up in 1.9.3.

All:  Please disregard the above advice unless, like me, you still have to work in a monolithic Rails app on old versions of just about everything.  :)

-Sam

Avdi Grimm

unread,
Jan 8, 2014, 3:23:10 PM1/8/14
to objects-...@googlegroups.com

Yeah there are huge perf differences in the delegate libraries 1.8 vs 1.9. Also be aware that 2.1 addresses a lot of the method cache issues because there is no longer a single global cache.

Steve Jorgensen

unread,
Feb 12, 2014, 2:12:35 AM2/12/14
to objects-...@googlegroups.com
Hi Rafael,

What about using a mock of the service/interactor object that acts as a shunt between the action method and a listener?

In order to allow mocking of services/interactors on controllers, I usually have a private method of the controller that returns the service/interactor class or delegates to its constructor. You can then stub that method in your tests to let you inject a test double.

-- Steve J.

Louis Simoneau

unread,
Mar 4, 2014, 5:27:33 AM3/4/14
to objects-...@googlegroups.com
On Thursday, 9 January 2014 05:20:42 UTC+11, Mike Kelly wrote:

Hey Rafael,

Stick the callback methods in SimpleDelegator, wrap the controller in it and pass that to your service object, test the delegator in isolation by making it wrap a mock and verifying each callback method makes the expected  ActionController API calls.

What about the controller itself? To test actual UI-level stuff like redirects, you need to have the mocked service objects actually fire the callbacks, which seems like a lot of overhead in the test.

Mike Kelly

unread,
Mar 4, 2014, 5:32:51 AM3/4/14
to objects-...@googlegroups.com

Sorry, I'm not sure I understand the question - can you gist an example?

Cheers,
M

Andy Waite

unread,
Apr 30, 2014, 5:14:01 PM4/30/14
to objects-...@googlegroups.com
I wrote a sample hexagonal controller with specs a few days ago which might help:


Andy
Reply all
Reply to author
Forward
0 new messages