---
title: How to Test Sinatra-Based Web Services
teaser: Testing http endpoints in sinata apps.
tags: web,ruby,http,testing
author: Harlow Ward
published_on: 2013-03-17
---

Sinatra is a fantastic lightweight framework for building web services.  We'll
use it as the application framework for the HTTP endpoints in our Service
Oriented Architecture.

The testing approach will be in-process, which means that the test suite is
running in the same Ruby process as the web service. This eliminates the need to
run an external HTTP web server.

## Application structure

Unlike Rails, Sinatra isn't all that opinionated on how  you set up your
application (it has a few [sensible
defaults](http://www.sinatrarb.com/configuration.html)), which can lead to a lot
of open questions on how to structure the application.

Here's the directory structure we'll use for our example application.

    app/
    app/models
    app/my_service.rb
    client/
    client/lib/my_client.rb
    client/my_client.gemspec
    config/
    spec/

## Outside-in development with a Client Gem

For internal services we'll build a client gem directly into the project. With
the client embedded in our codebase we can follow outside-in development cycles
-- Features start with request specs from the client side, followed by the
addition of end points to the service, and then unit tests within the
application.

This allows the us to
[dogfood](http://en.wikipedia.org/wiki/Eating_your_own_dog_food) our client gem
and bring it in as the first step of our development process.

To achieve this we need to configure a few things.

1.  Set up the project gemfile to use a local copy of the client in test mode

    Include the local client gem in test suite.

    ```ruby
    # Gemfile
    group :test do
      gem 'my_client', path: 'client'
      gem 'webmock'
      # ...
    end
    ```

2.  Use webmock to send all http requests to the service

    Instead of booting up a web server every time the test suite is run we'll
    mount the Sinatra service as a rack application with webmock.

    This allows the client to talk directly to the mounted rack application
    without going through HTTP or a web server.

    ```ruby
    # spec/spec_helper.rb
    RSpec.configure do |config|
      config.include WebMock::API

      config.before(:each) do
        MyClient.base_url = 'http://www.example.com'
        stub_request(:any, /www.example.com/).to_rack(MyService)
      end
    end
    ```

3.  Use the client in our request specs

    Once `MyService` is mounted as a rack application we can use the client
    gem directly in our test suite.

    ```ruby
    # spec/requests/widget_management_spec.rb
    require 'spec_helper'

    describe "Widget management" do
      it "creates a Widget" do
        # set up fixture data if needed

        response = MyClient::Widget.create(widget_params)

        # assert expectations on the response
      end
    end
    ```

## Private gem hosting

To use the client gem in other projects we can use a private gem hosting service
like [Gemfury](http://www.gemfury.com/). This allows us to include the client
via gemfile in our other projects.

```ruby
# Gemfile
source 'https://452f6E403CDph10714e41@gem.fury.io/me/'
gem 'my_client'

source 'https://rubygems.org'
# ...
```

## Takeaways

* Sinatra is great framework for creating lightweight web services.
* Webmock allows us to test the client in-process against a rack application.
* Use private gem hosting to distribute the shared client.
