Skip to content
Travis Douce edited this page Apr 8, 2014 · 74 revisions

Create factory_girl factories remotely using remote_factory_girl in conjuction with remote_factory_girl_home_rails.

Why RemoteFactoryGirl and RemoteFactoryGirlHomeRails?

Integration testing Software Oriented Architecture (SOA) apps is an inherently difficult problem (Rails apps included:). SOA is comprised of multiple applications, and while individual apps can be tested (and presumably passing) in isolation (usually by mocking http requests), it does not guarantee the apps will work in unison. Testing interactions between apps is more difficult.

One problem with integration testing SOA apps is that it is difficult to write integration tests from the client. Due to the nature of SOA, it is difficult to create the data you need, from the client's perspective, because the database resides in another application. Consider the following architecture:

client-home-architecture

The home application contains the database, and the client application does not have a database. If the client application wants a list of all the users, it has to make an http JSON request to home, home requests all the users from the database, and home sends the response back to the client.

The problem with integration testing SOA apps

Given the architecture above, assume we want to write an integration test that tests that a user can see all their friends in the client application. Also, assume that the user must sign-in to the client application. This test requires that the following test data be set up in the home app:

  1. A user must be created in the home application's database
  2. Friends must be created in the home application's database
  3. These friends must be associated with the user in the home application's database

Also, the client application must know the username and password of the user that was created in the home application so that the client application can fill-in the username and password fields with the user's username and password, and then click the 'Sign-in' button. In other words, there is a large amount of data needs to be created in order to test that a user can see all their friends in the client application

In traditional applications (apps that contain a database), it is possible to create test data with tools such as factory_girl. However, in SOA apps factory_girl alone does not suffice. remote_factory_girl, when used in conjunction with remote_factory_girl_home_rails, provides a mechanism to create the data you need in the home app from the client app by building on top of factory_girl (because we all work on the backs of giants).

Installation

remote_factory_girl should live in the client application and remote_factory_girl_home_rails should live in the home app (the app with factory_girl factories).

Client App

Add this line to the client application's Gemfile:

group :test do
  gem 'remote_factory_girl'
end

And then execute:

$ bundle

Or install it yourself as:

$ gem install remote_factory_girl

Configure

Basic Configuration

Configure in spec/spec_helper.rb

RemoteFactoryGirl.configure do |config|
  config.home = { host: 'localhost', port: 5000, end_point: '/remote_factory_girl' }
  config.return_with_root = false
  config.return_response_as = :dot_notation
end

Use in specs

require 'spec_helper'

describe User do
  it 'should create a user factory in RemoteFactoryGirlHome' do
    user = RemoteFactoryGirl.create(:user, first_name: 'Sam', last_name: 'Iam')
    expect(user.first_name).to eq('Sam')
  end
end
ActiveResource Configuration

If your apps are configured to use ActiveResource, then have remote_factory_girl return ActiveResource objects.

Configure in spec/spec_helper.rb

RemoteFactoryGirl.configure do |config|
  config.home = { host: 'localhost', port: 5000, end_point: '/remote_factory_girl' }
  config.return_as_active_resource = true 
end

Clean database between specs (recommended)

See remote_database_cleaner for installation and configuration

Configure in spec/spec_helper.rb

RSpec.configure do |config|
  config.after(:before) do
    RemoteDatabaseCleaner.clean
  end
end

Use in specs

require 'spec_helper'

describe User do
  it 'should create a user factory in RemoteFactoryGirlHome' do
    user = RemoteFactoryGirl.create(:user_with_friends, first_name: 'Sam', last_name: 'Iam').resource(User)
    expect(user.first_name).to eq('Sam')
  end
end

Home App

Add this line to home application's Gemfile:

group :test do
  gem 'remote_factory_girl_home_rails'
end

And then execute:

$ bundle

Configuration

Configure in config/environments/*.rb

Activate remote_factory_girl_home_rails to run in the environments in which it is intended to run. For example, if remote_factory_girl_home_rails is included in group :test (most common), then activate it in config/environments/test.rb

YourApplication::Application.configure do
  ...
  config.remote_factory_girl_home_rails.enable = true
  ...
end

Configure in config/routes.rb

YourApplication::Application.routes.draw do
  if defined?(RemoteFactoryGirlHomeRails::Engine)
    mount RemoteFactoryGirlHomeRails::Engine, at: '/remote_factory_girl' 
  end
end

Configure in config/initializers/remote_factory_girl_home_rails.rb

Specify any methods that should be skipped for incoming http requests. The most common methods to skip are authentication related methods that live in ApplicationController.

RemoteFactoryGirlHomeRails.configure do |config|
  config.skip_before_filter = [:authenticate, :some_other_method]
end if defined?(RemoteFactoryGirlHomeRails)

Use Together

Home Application

  1. Run any outstanding migrations.
  2. Start the home application's server with the correct:
    • environment
    • port
    • end_point

Given the configuration from the examples above, start the home server with:

$ rails server --environment=test --pid=/Users/your_app/tmp/pids/your_app-test.pid --port=5000

Client Application

  1. Run your test suite.
$ rspec
Clone this wiki locally