On Sunday, April 15, 2012 at 9:23 PM, Rodrigo Rosenfeld Rosas wrote:
> Em 14-04-2012 10:11, David Chelimsky escreveu: 
> > On Friday, April 13, 2012 at 2:09 PM, Rodrigo Rosenfeld Rosas wrote:
> > > Hello old friends, I'm getting back to Rails and Ruby programming full 
> > > time again (Yay!)
> > > 
> > > I've stopped doing Rails programming to work with Grails in 2009 after 2 
> > > years working with Rails due to a better job offer.
> > > 
> > > Since then I've changed my job once more, but still on Grails, but I 
> > > found a critical bug in Grails more than a week ago that didn't seem to 
> > > get much attention and is affecting the production system I maintain:
> > > 
> > > http://jira.grails.org/browse/GRAILS-8994
> > > 
> > > As I couldn't work around that bug and I can't see myself reading the 
> > > Grails source code (a real mess!) I decided to take another approach that 
> > > would allow me to get back to Rails programming.
> > > 
> > > I created a Devise / Warden strategy to send the cookies to the current 
> > > system and it will return me the current logged in user. So I can set up 
> > > Nginx to proxy some requests affected by the Grails bug to this new Rails 
> > > application.
> > > 
> > > I've finished this action last Monday but when I was about to send all 
> > > the hard work to the server lots of my directories were suddenly gone 
> > > when I was using them. I still don't know what happened but I've replaced 
> > > my hard-drive just in case, but it means I had to do all over again :(
> > > 
> > > Anyway, now I got it back to work but testing a single action (an 
> > > update/insert one) will take about a full second to run using RSpec and 
> > > FactoryGirl.
> > > 
> > > I really don't like Grails but they had a great feature for unit testing. 
> > > They were able to mock their domain class (that is how they call their 
> > > models) in such a way that they can perform most of the operations you 
> > > can do on real objects.
> > > 
> > > Of course it have another serious bug that will prevent me to use it in 
> > > lots of cases:
> > > 
> > > http://jira.grails.org/browse/GRAILS-8854
> > > 
> > > But the idea is great as it works seamlessly like in a memory database.
> > > 
> > > So, I'd like to be able to keep my tests easy to read but avoid touching 
> > > the database that much.
> > > 
> > > But my controller spec rely on lots of the setting of ActiveRecord for my 
> > > models, like maximum calculations in before callbacks, custom foreign 
> > > keys and depends: :delete_all in some has_many associations. Also I do 
> > > also need a user object that Devise will accept on its sign_in helper 
> > > method.
> > > 
> > > Is there any place I could read more about writing faster tests without 
> > > getting crazy writing so many mocks manually. For example, mocking a 
> > > Grails domain class in a unit test would be as easy as:
> > > 
> > > @mock(User)
> > > class UserTests...
> > > 
> > > Then I'm able to do most operations using the Grails domain class API 
> > > using the User mock.
> > > 
> > > Is there something like this for Rails and Rspec? Is there some way that 
> > > I could set up FactoryGirl to use those mocks instead of hitting the 
> > > database when I want to?
> > > 
> > > Am I going in the wrong direction here? If so, what would be the right 
> > > direction?
> > > 
> > > Thanks in advance.
> > > 
> > > Glad to be part of the Ruby, Rails and Rspec community full-time again :D
> > > 
> > > Cheers,
> > > Rodrigo. 
> > You can use mock_model or stub_model to create model instances, or you can 
> > use FactoryGirl.build instead of FactoryGirl.create. Only mock_model will 
> > actually avoid db calls entirely (the others will still query for column 
> > names even if you don't save anything).
> > 
> > Those techniques, however, don't help you with finders. You still have to 
> > stub any finders with the object generated by any of the aforementioned 
> > techniques: 
> > 
> > thing = mock_model(Thing) 
> > Thing.stub(:domain_specific_finder => [thing])
> > 
> 
> 
> I'm not sure what you're suggesting. For example, the first part of my 
> controller action looks like this:
> 
> instance = Model.where(id: params[:id]).first_or_initialize(parent_id: 
> params[:parentId])
The controller is interacting with an ActiveRecord API on the model instead of 
a domain-specific-finder. I'd recommend wrapping this in a method on the model 
and then mocking _that_ method.
> The spec starts with something like this:
> 
> root = FactoryGirl.create :field, label: 'ROOT'
> post 'action', parentId: root.id
> 
> In the before/after Model callbacks there will be other kind of finders for 
> the same class.
Think I'd need to see more of the code to comment on this.
> How would you suggest me to change this block to use FactoryGirl.build and 
> mock Model?
Use one or the other (they both serve a similar purpose).
> Also, I couldn't find how to mock 'open' from 'open-uri', so I'm currently 
> mocking my controller's action:
> 
> controller.should_receive(:clear_fields_cache).exactly(3).times # 1 creation 
> and 2 updates
> 
> The action is implemented this way:
> 
> require 'open-uri'
> ...
> private
>   def clear_fields_cache
>     open INTEGRATION_BASE_URL + 'clearModelCache',
>       'Cookie' => authentication_cookie_string # includes JSESSIONID and 
> rememberMe
>   end
> 
> But maybe it would be a great idea to check for the specific URL and cookie 
> handling and I could do so if I was able to mock the 'open' method from 
> 'open-uri'. Any ideas on how to do that?
I use https://github.com/chrisk/fakeweb for this sort of thing. It operates 
more like a stub than a message expectation.
> > It's not pretty, but it's the best way I know of to get what you're after. 
> > I started a lib called stubble a few years back that attempted to address 
> > this more holistically (https://github.com/dchelimsky/stubble) but I never 
> > released it as a gem because there were just too many different ways to 
> > access model data via the ActiveRecord API and they don't all flow through 
> > a single part of the codebase that we can override in an extension.
> > 
> 
> I agree with you. I've taken a look at the library but as you can see I'm 
> using the new 'where' API and this probably will keep changing each new AR 
> release...
This is exactly why I like to wrap finders in domain-specific methods on the 
model :)
> Also, in Grails case, the mocked domain classes are maintained alongside with 
> the real classes, so there is little chance of them getting out of sync. But 
> of course the mocks have some limitation, like not being able to deal with 
> custom SQL fragments:
> 
> http://grails.org/doc/latest/guide/testing.html#unitTestingDomains
> 
> Other than that there are also some bugs when dealing with association ids.
> 
> I never thought it would be easy to have something like this for ActiveRecord 
> but once there is a long time since I last often worked with Rails, things 
> might have changed ;)
> 
> Thank you a lot for your input and glad to be talking to you again :)
> 
> Cheers,
> Rodrigo.
> _______________________________________________
> rspec-users mailing list
> rspec-users@rubyforge.org (mailto:rspec-users@rubyforge.org)
> http://rubyforge.org/mailman/listinfo/rspec-users
> 
> 


_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to