

Speed Up Your Rails Specs - handler
http://blog.originate.com/blog/2014/02/27/improve-your-rails-specification-speed-by-10x/

======
al2o3cr
"expect(widget_factory).to have_received(:create).with({name: 'sprocket'})"

Even better:

expect("my_service.rb", "line X").to be("widget_factory.create")

Or yet better, simply:

; # realize that testing the exact implementation is bullshit

------
xentronium
RE: Developing Decoupled Code

Extra complexity cost is insane and probably not worth it. Basically you move
all your crazy stubbing and mocking out of test code and into application
code. Do not do this unless you really, really need this kind of dependency
injection.

~~~
mattgreenrocks
Back in the day, we laughed at people who stuffed all their code into button
click handlers.

Now, we mock people who _don 't_.

My, how different the web is!

~~~
xentronium
That's a straw man. I see how you made it up for a joke, but it's still
confusing. "Don't overengineer" is not the same as "stuff all your code into
button click handlers".

------
jdminhbg
I like that the "tightly coupled" service class is 3 extremely simple LOC that
should probably just be in a controller anyway, which is "fixed" by creating a
class with 3X as many methods and at least twice as much logic to follow, plus
a spec twice as long as the original class that tests nothing other than the
fact that when you call a method with a set of arguments, that method receives
that set of arguments.

------
ryanbrunner
I have a massive, and probably not entirely proportionate, negative reaction
to constructor injection. It's in my mind the ultimate example of making your
code more complex in service of your tests.

An approach that I've used recently (which is similar enough to parameter-
style injection, is to use `class_attribute` at the top of a class to call out
dependencies and explicitly provide a default value - so that consumers of
your class don't need to know what exactly a WidgetFactory is supposed to be:

    
    
        class Foo
          class_attribute :some_service
          self.some_service = SomeService.new
        end
    

A nice advantage of this approach is that you can provide a different
implementation of some_service on an individual instance of a class, which
helps restore your code to a sane state when you're done with an individual
test, like so:

    
    
        describe Foo
          subject(:foo) { Foo.new }
          before { foo.some_service = double(SomeService).as_null_object }
        end
    

On top of that, though, I think calling out dependencies really only makes
sense when that dependency involves something external to the codebase itself,
or is otherwise secondary to the main purpose of the class. So stub out a
repository, or a logger to your hearts content - but there's little utility in
stubbing out Widget in a WidgetBuilder class IMO.

------
mcmire
The problem with dependency injection in this manner is that your test code is
using a fake class that's injected while your production code is using a real
class.

This is fine if all you want to do is unit test your classes. That's beside
the point though -- I would posit if you're bolting dependency injection onto
your interfaces just to make your tests faster, you're not doing it right.
Instead, bring that dependency injection into the forefront: to the
constructor. Yes, this means to make an object, you'll have to make another
object first, both in your production and test code. But now your interface
acts the same way in both places. If this sounds very Java-like, well... maybe
Java got it right. (There was an article on the Twitter blog in the early days
about this but I can't remember where it is now...)

Of course, this _is_ going to introduce complexity and now you have to decide
whether that complexity is worth it.

------
joevandyk
Maybe if ruby didn't take so long to load rails code, this sort of complexity
wouldn't be necessary...

