On Jan 27, 2011, at 7:48 AM, Michael Guterl wrote:

> We have moved from Rails 2 to 3 and the changing Mailer syntax has
> caused us to rewrite some of our specs.
> 
> In Rails 2:
> 
> Implementation:
>  Mailer.deliver_job_application(job.id, user.id)
> 
> Spec:
>  Mailer.should_receive(:deliver_job_application).with(@job.id, @user.id)
> 
> ---
> 
> In Rails 3:
> 
> Implementation:
>  Mailer.job_application(job.id, user.id).deliver
> 
> Spec:
>  message = double
>  message.should_receive(:deliver)
>  Mailer.should_receive(:job_application).with(@job.id,
> @user.id).and_return(message)
> 
> ---
> 
> I turned the latter example into a matcher for RSpec 2 and I'm open
> for feedback.
> 
> Here's a gist incase the inline formatting sucks: 
> https://gist.github.com/798513
> 
> RSpec::Matchers.define :deliver do |message|
>  chain :with do |*args|
>    @with = args
>  end
> 
>  match do |mailer|
>    mail = double
>    mail.should_receive(:deliver)
> 
>    mailer.should_receive(message).with(*@with).and_return(mail)
>  end
> end
> 
> Mailer.should deliver(:job_application).with(@job.id, @user.id)
> 
> ---
> 
> Is this a sane approach?

I think it's sane for inside your own app, but not as part of a lib. First, 
it's bound to rspec-mocks, and including it in an rspec lib would require extra 
handling to either make it only available for rspec-mocks or make it support 
the other frameworks that rspec supports. Second, it hides a message 
expectation. Again, that's fine for your own app, in which you know what's 
going on, but would confuse some users if it were in a lib.

Make sense?

> Would it have been better to adapt the
> Mailer interface to comply with the specs?

That's a funny thing. There are a lot of things that I think would work 
differently in Rails API's if they were driven out with a TDD mindset. But the 
API's seem to be designed with rapid prototyping in mind more than long term 
maintainability. For example, I'd really like to be able to write a controller 
example like this:

# not anything close to reality
controller = ThingsController.new
response = controller.action(:some => 'params')
response.should be_redirect_to(:action => 'other')

But we don't really have a public API for instantiating controllers, which is 
why we have the http verb methods, which conflate routing concerns with 
controller concerns.

I'm not judging these choices as good or bad. Just observing one aspect of the 
resulting 'feel'.

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

Reply via email to