[rspec-users] Specs and Libs

David Chelimsky dchelimsky at gmail.com
Thu Oct 4 07:24:01 EDT 2007


On 10/4/07, Nathan Sutton <nathan.sutton at gmail.com> wrote:
> How would I go about writing specs for a lib, particularly one with
> all protected and private methods.  I'm trying to spec the
> AuthenticatedSystem library from the rails restful_authentication
> plugin:
> http://pastie.caboo.se/103625

I think there are a few ways you can handle this. One would be to
create a class that includes that module and add public methods to
that class that access the protected ones:

class ExampleController
  include AuthenticatedSystem
  def has_logged_in_user?
    logged_in?
  end
end

controller.should_not have_logged_in_user
log_in #waving hands...
controller.should have_logged_in_user

Other possibilities would be to use instance_eval or make the methods
public from the example using send(:public, :logged_in?). I to avoid
that sort of thing when I'm developing code spec-first, but in the
case of back-filling specs on existing code I don't mind using brute
force like that. It's brittle, and in the end I might want to change
the design, but not until I've got it fairly well covered so I can
refactor in peace.

>
> Also, when you're mocking objects, a side-effect is helping you
> define the api of the object.

Actually, I think that's the whole point of mock objects and not a
side effect at all. If anything, the side-effect is isolation :)

> Is there a way to get all the
> behaviors that have been mocked for a class and its objects?  Is
> there a way to automagically compare the output against what is
> actually defined?

Mocha allows you to do this using responds_like:

account = mock('Account').responds_like(Account)
account.expects(:withdraw)

If account does not respond_to?(:withdraw), then you get a failure.

Personally, I never use this. In practice, it means that every time I
say object_i_am_NOT_defining_right_now.expects(:method_that_does_not_exist_yet)
I have to stop what I'm working on and add this method to the real
object. In the best case scenario, I'm disciplined about it and I
start writing specs for the new behaviour - completely losing the
context I was just in. In the less-than-best-case scenario, I'm not as
disciplined and I just add an empty method declaration in order to
quiet the noise. Neither case is desirable for me.

We've batted the idea of adding support for something like this to
rspec's mock framework, but with a command line switch to turn it on
(default behaviour would be that it stays quiet). There's an open RFE
for this in the tracker. I'm just not sure that it's worth the trouble
when you consider the implications of behaviour getting added at
runtime and the like.

FWIW,
David

>
> Thanks,
>
> Nate "fowlduck" Sutton
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>


More information about the rspec-users mailing list