On Tue, Oct 21, 2008 at 5:45 AM, Rob Lacey <[EMAIL PROTECTED]> wrote: > > However, I seem to dread spec-ing out controllers, they end up being quite > untidy, I think maybe I am approaching them in the wrong way as it probably > shouldn't be as hard as I am making it.
For what it's worth, Rob, I'm totally with you. The generated code for controller specs has always felt...well, wrong to me. And it's been a frustration every time I've sat down to try to write new controller specs the same way, taking many times longer than it takes to write the controller. The bad part has been the work required to set up the stubs and mocks -- for just the reason you cite. Conforming to the "single expectation per test" pattern means I have to figure out and stub every method that gets called and make it return a reasonable value, and then I have to *mock* each call at least once to confirm that it gets called. By this point I've essentially written the model interface twice, which feels like extraordinary extra work -- and it also feels brittle. Reasonable changes in the model require unreasonable maintenance in the controller stubs and mocks. The only reason for all of this work is the principle of code isolation. You're supposed to make sure you're only running the code in the unit you're testing -- but because controllers sit at the heart of your app, *of course* they're going to have a great deal of interaction with everything else. That isn't wrong and it doesn't necessarily make the controllers too fat. But it makes the testing fat. Just stubbing the relationship between model collections and objects is complex. It also looks screwy -- and it isn't really a test of the controller. But it has to be done if you're not going to talk to the model. There are some cheats, of course. You can make blanket responses to stuff you don't feel like mocking. The null_object option to RSpec mocks is such a cheat; so's stub_everything in Mocha. But to me they feel like copouts, and they return null by default, which is most often the wrong behavior, so they don't save work. Mock_model and stub_model are intended for views, and stub_model doesn't isolate you from the model. There are some extension plugins that do some of the mocking/stubbing "grunt work" for you, but that reduces transparency and they don't know about anything but the most common 'formula' methods. The conclusion I'm starting to reach is that it often isn't worth it. All these hours of work to avoid talking with actual models... But if you just plain used the models, so what? Yes, your controller specs could fail if your model is buggy or unimplemented. But if your model's properly spec'ed you'll get failures on the bug there too, pinning the problem down, and the implementation constraint simply means you can't write models *last*. You'd implement methods on them before or simultaneous with the controllers that call them. That's not a bad order of things. So now I'm experimenting with live models. I'm using simple, basic factory methods (I use fixture_replacement2) to create objects for my controller specs to operate on, saved or unsaved as necessary, and using Mocha to inject expectations into the actual objects for specific examples. I may look at not_a_mock for that, too, now that it's being talked about here. This may not be as philosophically pristine as total isolation, but it's simpler and cleaner. You don't have to replicate fake model complexity it in the controller spec. Most of the lines in the controller spec are once again about the _controller,_ not about setting up models. It's also slower, but only a bit. Even with autospec, waiting on my tests to begin is already slow enough that I don't feel it makes a huge difference. I'm documenting my approach, too, and what I've been thinking and learning about RSpec from a "thoughtful beginner" perspective, and hope to have something I can post on that soon. (That documentation is, in fact, one of the motivations for my current project.) That's my take. It's working for me so far, but with the caveat that I haven't carried a project through to completion with this approach. If any of the _cognoscenti_ can offer reasons why this is a horribly bad idea that'll blow up in my face sooner or later, I'm open to being convinced. I also offer my apologies if this is a topic that comes up on this list over and over again, and if my little rant here is a common and tired one. -- Have Fun, Steve Eley ([EMAIL PROTECTED]) ESCAPE POD - The Science Fiction Podcast Magazine http://www.escapepod.org _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users