RSpec and Faraday
I recently integrated a gem into a project at work that used Faraday for some internal stuff. The main thing to understand is that I had to prevent any Faraday errors from bubbling up to the top level project. As such, I attempted to mock out some of the Faraday methods to return exceptions and ensure they were being handled correctly. That may not have been the right thing to do in terms of testing, as it meant I was mucking about in the internals of our external gem dependency. But it did lead me to discover a recent feature of rspec that I had missed on its release: verifying partial doubles.
Verifying doubles ensure that the underlying class actually implements the methods
you are attempting to mock. And attempting to mock the Faraday.get
method kept
raising rspec errors that the underlying class didn’t actually implement the method.
I was completely confused by the errors. I had totally missed that particular feature becoming the default in rspec.
After I finally checked the Faraday source, it turns out that GET
, HEAD
, and
DELETE
are implemented via class_eval
That makes some sense, given Faraday’s architecture (i.e., it’s effectively an
HTTP API on top of whatever underlying HTTP library you want to use). But it also
explained why rspec was freaking out since the methods weren’t specifically defined
on the class.
There’s a bit of an impedance mismatch here that I want to point out. One of the really neat things about ruby is that you get to do fun metaprogramming type things when you need to. On the other hand, I can really see the utility of verifying partials, as you’ll want to ensure that your tests are relying on real methods that have been implemented. You don’t want drift to catch you by surprise.
Faraday is using a nifty rubyism that avoids some boilerplate, repetitive code. And the verifying partials don’t really agree with that world. In fact, rspec has a page about how to work around the impedance mismatch.
I find the tension I see between these two approaches fascinating. Neither approach
is bad or wrong in any sense. RSpec definitely provides mechanisms to work around
classes that use method_missing
or other metaprogramming hooks, although for my
use case, I’m not sure that it would have been worth it to go through that level
of extra work. With that said, I greatly appreciate the attempt to provide some
level of an interface guarantee from within my testing toolkit, and I anticipate
exploring that tooling more in the near future.