Read The Times Australia

Daily Bulletin

Gateway classes: a pattern for interacting with external services

  • Written by: James Healy, Technical Director, The Conversation

Rails encourages developers to use a database in integrated acceptance tests, and we’ve gone with the flow on that front.

However, like many rails apps we also integrate with a number of external services that are more difficult to deal with in tests - stripe, campaign monitor, akismet and slack are good examples. In most cases these services are accessed over the internet and operated by external companies, so to keep our tests fast and reliable we’ve opted to stub them rather than change any remote state.

To begin with, we were inconsistent with where and how we stubbed these services, exploring solutions like rspec mocks, vcr and plain webmock.

As our product grew and we integrated new services, we started to look for a pattern we could standardise on. Our goals for the new pattern were:

  • Avoid all network activity to external services during tests
  • Encourage happy path acceptance tests to avoid excessive build times
  • Rely on unit tests to thoroughly test code that calls the external service, including error cases and intermittent network issues
  • Avoid excessive setup for acceptance tests
  • If we’re using an external gem, encapsulate it with code we own to simplify future refactoring

We settled on a pattern we called “Gateway Objects”, inspired by a Martin Fowler refactoring article.

We store them in app/gateways/ and have added the following line to config/application.rb so rails can find them:

config.autoload_paths << Rails.root.join("gateways").to_s

In most cases we use a fraction of the external service’s functionality, so our gateway classes have public methods for just the bits we need. Each method has extensive unit specs, usually relying on webmock to avoid hitting a live HTTP API.

Where possible, our gateways return objects that are either from ruby core (Integers, Strings, Hashes, Arrays, etc) or immutable value objects that we control.

Here’s a simplified example that adds subscribers to a Campaign Monitor list. It relies on the createsend gem, and uses webmock for unit specs.

require 'createsend'

class CampaignMonitorListGateway
  def initialize(list_id, api_key: nil)
    @list_id = list_id
    @api_key = api_key || ENV.fetch("CAMPAIGN_MONITOR_KEY")
  end

  # add a new email address to this list
  #
  def subscribe(email)
    CreateSend::Subscriber.add(
      {api_key: @api_key},
      @list_id,
      email,   # email address
      email,   # name
      [],      # custom fields
      false    # resubscribe
    ) == email
  end
end

Exhaustive unit specs allow us to focus our integrated acceptance tests on a happy path, so we usually stub the gateway to return a consistent result across all tests with the some configuration in spec/rails_helper.rb:

RSpec.configure do |config|
  config.before :each, type: :feature, stub_cm_list: true do
    allow(CampaignMonitorListGateway).to receive(:new) {
      instance_double(CampaignMonitorListGateway, subscribe: true)
    }
  end
end

With that, any acceptance test can use metadata to declare a need for stubbing.

feature 'A reader subscribing to our daily newsletter' do
  scenario "from a topbar link", :js, :stub_cm_list do
    # some assertions
  end
end

Most method calls on a gateway class will result in network activity and lots can go wrong when networks are involved. We avoid silently swallowing exceptions, and either:

  • catch the exception, notify our error tracker, and return a Null object; or
  • allow the exception to bubble out so the caller deals with it

We’re pretty happy with the final result – our test setup is cleaner, the tests are acceptably fast and pass without internet access, and the shared vocabulary helps us maintain team code in a consistent style over time.

Authors: James Healy, Technical Director, The Conversation

Read more http://theconversation.com/gateway-classes-a-pattern-for-interacting-with-external-services-65633

Business News

Inside the Icon: The BridgeMuseum Officially Opens at the Sydney Harbour Bridge

A bold new way to experience one of Australia’s most recognisable landmarks has arrived, with BridgeClimb Sydney officially opening the all-new BridgeMuseum.  Located inside the Sydney Harbour Brid...

Daily Bulletin - avatar Daily Bulletin

Is Your Brand Showing Up in AI Search? Most Melbourne Brands Aren't.

The New Front Door Nobody Told You About Something changed. Quietly. Without a press release. The way buyers find businesses in Australia has been rewired. Not replaced, rewired. Google isn't dead...

Daily Bulletin - avatar Daily Bulletin

How Australian Businesses Can Measure SEO ROI

SEO can feel vague when you are staring at a dashboard full of numbers that do not clearly connect to revenue. The key is to measure the right signals in the right order, then tie them back to outcome...

Daily Bulletin - avatar Daily Bulletin

How Commercial Roller Shutters Improve Site Security Without Slowing Operations

Security upgrades can be frustrating when they make everyday work harder. A door that takes too long to open, creates bottlenecks at shift change, or fails at the worst time can turn “better protectio...

Daily Bulletin - avatar Daily Bulletin

Why a Document Destruction Service Still Matters for Modern Businesses

Businesses generate large volumes of information every day, from staff records and contracts to invoices, reports and customer files. While attention often focuses on how documents are stored, the way...

Daily Bulletin - avatar Daily Bulletin

Bicycle Rack Safety and Space-Smart Storage

Bike storage problems usually show up as small annoyances first: tangled handlebars, scratched frames, and bikes that topple when you pull one out. Over time, those issues become safety risks, especia...

Daily Bulletin - avatar Daily Bulletin

How to Tell if a Childcare Centre Is a Good Fit for Your Child

Choosing childcare can feel like you’re making a huge decision with limited information. Tours are short, centres are often on their best behaviour, and your child might act differently in a new space...

Daily Bulletin - avatar Daily Bulletin

Car Import Timeline: What Usually Happens at Each Stage

Importing a car into Australia can feel confusing because multiple agencies and checkpoints are involved, and the timeline is shaped as much by paperwork quality as it is by shipping speed. The most u...

Daily Bulletin - avatar Daily Bulletin

Portable Toilet Hygiene Standards Explained: Clean vs Sanitised vs Disinfected

In portable toilet servicing, the words clean, sanitised, and disinfected often get used as if they mean the same thing. They don’t. And that difference matters because a unit can look tidy and still ...

Daily Bulletin - avatar Daily Bulletin

The Daily Magazine

The pressure cooker: life in urban Australia in 2026

Australian cities have always been demanding. Long commutes, rising housing costs, busy schedules a...

What Actually Makes a Good Criminal Lawyer in Melbourne

Most people only think about this question once. That is usually too late. Most people charged wi...

Why Working With A Chatswood Tutor Can Improve Academic Performance

Academic expectations continue increasing for students across primary school, high school, and senio...

Is It Worth Getting Solar Panels in Melbourne?

The real question is not whether solar works in Melbourne. It works. The question is what it is co...

How A Diploma Of Project Management Builds Practical Skills For Modern Work Environments

Developing the ability to plan, execute, and deliver outcomes efficiently is a key requirement in to...

How to Choose the Right Football for Every Level

Choosing a football may seem straightforward, but the right option depends on who will be using it a...

What to Ask a Wedding Photographer Before You Book

Booking a wedding photographer can feel deceptively simple: you like the photos, you like the vibe...

Why Stress Relief For Dogs Is Essential For Emotional Balance And Long-Term Wellbeing

Managing emotional health is just as important as physical care when it comes to pets, which is why ...

Australia’s Best Walking Trails and the Shoes You Need to Tackle Them

Australia is not short on spectacular walks. You can follow ocean cliffs in Victoria, cross ancien...