[rspec-users] feedback on matcher

Michael Guterl mguterl at gmail.com
Thu Jan 27 13:49:13 EST 2011


On Thu, Jan 27, 2011 at 10:30 AM, David Chelimsky <dchelimsky at gmail.com> wrote:
>
> 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?
>
Definitely, although I'm sure I'm not the only one verifying Mailers
in this way, it'd be nice to have a library.

>> 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.
>
This is certainly an interesting point that you bring up.  I had never
really considering the "why" in why we write controller specs like we
do.

Thanks for your insight David.

Best,
Michael Guterl


More information about the rspec-users mailing list