The main idea is to override implementation dynamically during the call of external service. In other words, to use different sources for receiving data for different environments. Suppose for production environments, you get the data from a third-party server, and for a test environment, the source can simply return an object of the desired format.

Bridge Pattern: class with abstraction

First of all, we separate responsibilities in different classes. According to the Bridge pattern, it needs to decouple an abstraction from its implementation.

Here we implement the abstraction with the external service call, and here we will introduce the dependency:

cattr_accessor: source allows us to determine which class will participate in the loading of posts.

Bridge Pattern: the Implementators

We need to have implementations: one for the real external service call, another will be called in tests.

Call to real API will look like:

And the fake implementation:

Note: All source implementations must have the same interface.

How does it work

When we need to use the external service:

To use Fake implementation:

Settings for various environments

According to Ruby on Rails way, the settings for various environments need to be placed in the initializer.

First, let’s set the default value for the source:

For the convenience of testing the code associated with the Medium class, you can make a separate class that will manage the source attribute.

Now in the initializers folder, let’s create the file with necessary configurations:

In this way PostsSource::Fake will be used for the test environment and PostsSource::Medium the other environment.

Benefits received

The real response still needs to be tested, and most likely, it will be stubbed. But dependency injection allows decreasing the number of stubbing usages in the tests.