Created
March 28, 2012 08:52
-
-
Save pda/2224862 to your computer and use it in GitHub Desktop.
Simple Dependency Injection and MiniTest::Mock
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "addressable/uri" | |
require "net/http" | |
module Ralexa | |
class Client | |
# Hacked to simplify example. Full version at: | |
# https://github.com/flippa/ralexa/blob/master/lib/ralexa/client.rb | |
def initialize(*credentials) | |
# ... | |
end | |
# Dependency injectors. | |
attr_writer :net_http | |
def get(host, path, query_values) | |
uri = signed_uri(host, path, query_values) | |
net_http.get(uri) | |
end | |
private | |
def signed_uri(host, path, query_values) | |
# ... | |
end | |
## | |
# Injectable dependencies. | |
def net_http | |
@net_http || Net::HTTP | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require_relative "spec_helper" | |
module Ralexa | |
describe Client do | |
# Hacked to simplify example. Full version at: | |
# https://github.com/flippa/ralexa/blob/master/spec/client_spec.rb | |
let(:client) do | |
Client.new("id", "secret").tap do |c| | |
c.net_http = net_http | |
end | |
end | |
let(:net_http) { MiniTest::Mock.new } | |
let(:response) { MiniTest::Mock.new } | |
it "returns the response body of HTTP GET to a signed URI" do | |
net_http.expect :get_response, "<xml/>", [ %r{^http://example.org/test\?.*Signature=} ] | |
client.get("example.org", "/test", "a" => "b").must_equal "<xml/>" | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "base64" | |
require "digest/sha2" | |
require "openssl" | |
module Ralexa | |
class UriSigner | |
# Hacked to simplify example. Full version at: | |
# https://github.com/flippa/ralexa/blob/master/lib/ralexa/uri_signer.rb | |
def initialize(*credentials) | |
# ... | |
end | |
# dependency injectors | |
attr_writer :digest | |
attr_writer :hmac_signer | |
attr_writer :base64_encoder | |
attr_writer :time_utc | |
def sign_uri(original_uri) | |
# there's more to it than this, but to illustrate dependency injection: | |
original_uri.dup.tap do |uri| | |
uri.query_values = uri.query_values.merge( | |
"Timestamp" => time_utc.strftime("%Y-%m-%dT%H:%M:%S.000Z"), | |
"Signature" => base64_encoder.encode64(hmac_signer.digest(digest, @key, uri.to_s)) | |
) | |
end | |
end | |
private | |
## | |
# Injectable dependencies. | |
def digest | |
@digest ||= OpenSSL::Digest::SHA256.new | |
end | |
def hmac_signer | |
@hmac_signer || OpenSSL::HMAC | |
end | |
def base64_encoder | |
@base64_encoder || Base64 | |
end | |
def time_utc | |
@time_utc || Time.now.utc | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require_relative "spec_helper" | |
require "addressable/uri" | |
module Ralexa | |
describe UriSigner do | |
# Hacked to simplify example. Full version at: | |
# https://github.com/flippa/ralexa/blob/master/spec/uri_signer_spec.rb | |
# UriSigner with dependencies injected. | |
def signer | |
UriSigner.new("id", "secret").tap do |rs| | |
rs.digest = digest | |
rs.hmac_signer = hmac_signer | |
rs.base64_encoder = base64_encoder | |
rs.time_utc = time_utc | |
end | |
end | |
# Mocked dependencies. | |
let(:digest) { MiniTest::Mock.new } | |
let(:hmac_signer) { MiniTest::Mock.new } | |
let(:base64_encoder) { MiniTest::Mock.new } | |
let(:time_utc) { Time.now.utc } | |
# Mock expectations and return values. | |
before do | |
hmac_signer.expect :digest, "the_hmac", [ digest, "secret", String ] | |
base64_encoder.expect :encode64, "base64_encoded\n", [ "the_hmac" ] | |
end | |
describe "for http://example.org/path?a=b" do | |
it "returns a signed URL" do | |
original_uri = Addressable::URI.parse("http://example.org/path?a=b") | |
signer.signed_uri(original_uri).query_values.must_equal( | |
"a" => "b", | |
"Signature" => "base64_encoded", | |
"Timestamp" => time_utc.strftime("%Y-%m-%dT%H:%M:%S.000Z"), | |
) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment