Simple Dependency Injection and MiniTest::Mock

I recently wrote a Ruby client for Amazon Alexa’s APIs, and thought I’d pull out an example of nice, simple dependency injection to facilitate unit testing. Nothing revolutionary or complicated, just good practice.

The example is based around a UriSigner class, normally used by the calling code like this:*credentials).sign_uri(uri)

The calling code doesn’t know or care that UriSigner depends on Base64, OpenSSL::Digest::SHA256 and OpenSSL::HMAC. The unit test for UriSigner, however, cares for two reasons.

Firstly, they’re external dependencies, and only need to be tested for correct usage, not correct implementation.

Secondly, these dependencies represent an encoder and a cryptographic hash function; they’re deterministic, but they return very opaque data which can make tests and their failure messages difficult to understand.

So instead of testing against magical (computed in advance) Base64 strings and HMAC hashes, I’ve used simple attr_writer dependency injectors:

The unit test can then inject MiniTest::Mock instances in place of the real Base64 and HMAC implementations, setting expected method calls and their return values:

As simple as that.

The same approach is used by the HTTP Client class to stub out actual HTTP calls via Net::HTTP. There’s great libraries like VCR, WebMock and FakeWeb for handling this, but sometimes it’s easier to keep it lo-fi:

This kind of dependency injection is one of many basic techniques which aren’t fancy enough to get a lot of press, but go a long way to keeping your objects and tests in order.

Got any thoughts? Hit me up, I’m @pda on Twitter, where I generally write about this kind of thing.