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

Options Available When a Company Faces Financial Distress

Financial distress can develop gradually or arrive suddenly, and when it does, the decisions made in the early stages often determine what options remain available later. Directors who act promptly ...

Daily Bulletin - avatar Daily Bulletin

What Healthcare Teams Look for When Choosing Specialist Surgical Supplies

In clinical environments, small details rarely stay small. A delayed instrument, a poorly matched device or inconsistent supply quality can affect theatre flow, staff confidence and patient outcomes. ...

Daily Bulletin - avatar Daily Bulletin

Reducing Sales Friction Through Centralized Content Delivery

Sales friction appears whenever buyers or sales teams face unnecessary obstacles in the buying journey. It can happen when information is hard to find, when messaging feels inconsistent, when product ...

Daily Bulletin - avatar Daily Bulletin

Why Choosing the Right Bollard Supplier Matters for Australian Businesses and Public Spaces

From busy CBD streetscapes to sprawling warehouse loading docks, bollards have become one of the most essential safety and security fixtures across Australia. Whether protecting pedestrians from veh...

Daily Bulletin - avatar Daily Bulletin

Why Modular Content Is Transforming Modern Marketing Teams

Modern marketing teams are expected to produce more content than ever before. They need to support websites, landing pages, email campaigns, social channels, product pages, sales enablement material...

Daily Bulletin - avatar Daily Bulletin

Everything You Need to Know About Getting Support from Optus

Whether you've been an Optus customer for years or you've just switched over, at some point you'll probably need to contact their support team. Maybe your bill looks different from what you expected. ...

Daily Bulletin - avatar Daily Bulletin

The Marketing Strategy That’s Quietly Draining Sydney Business Owners’ Bank Accounts

Sydney businesses are investing more in digital marketing than ever before. The intention is clear. More visibility should mean more leads, more customers, and steady growth. However, many business ...

Daily Bulletin - avatar Daily Bulletin

Why Mining Hose Solutions Are Essential For High-Performance Industrial Operations

In environments where the ground itself is constantly shifting, breaking, and being reshaped, every component must be built to endure. Mining operations are among the most demanding in the industria...

Daily Bulletin - avatar Daily Bulletin

The Reason Talented Teams Underperform

If you’re in business, you might have seen it before. A team of capable and smart people just suddenly slows down, and things start spiraling out of control. On paper, everything looks perfect, but ...

Daily Bulletin - avatar Daily Bulletin

The Daily Magazine

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...

Why Pre-Purchase Building Inspections Are Essential Before Buying a Home in Australia

source Have you ever walked through an open home and started picturing your furniture, family d...

5 Signs Your Car Needs Immediate Attention Before It Breaks Down

Car problems rarely appear without warning. In most cases, your vehicle gives clear signals before...

Ensuring Safety and Efficiency with Professional Electrical Solutions

For businesses in Newcastle, a safe and fully functioning workplace remains a key part of day-to-d...

Choosing The Right Bin Hire Solution For Hassle-Free Waste Management

When it comes to managing waste efficiently, finding the right solution can save both time and eff...

Why Cleanliness Is Critical In Childcare Environments

Children explore the world with curiosity, often touching surfaces, sharing toys, and interacting ...

What to Look for in a Reliable Australian Engineering Partner

Choosing an engineering partner is rarely just about technical capability. Most businesses can fin...

How to Choose a Funeral Home That Supports Families with Care

Choosing a funeral home is rarely something families do under ideal circumstances. It often happen...