FakeTTP
Purpose
When you are writing acceptance/integration tests for an application which makes HTTP requests to a remote service, sometimes you need to be able to test the interactions in different scenarios without talking to a real instance of the remote application.
FakeTTP is a standalone web application that allows you to mock requests (ie set and verify expectations on the requests your application makes, and return suitable responses to those requests).
Installation
Dependencies
FakeTTP uses Sqlite3 by default (although it’s possible to use another database by editing fakettp.yml
after installation).
It also depends on the sqlite3-ruby
, activerecord
and sinatra
gems, which will be installed automatically if necessary.
Install the gem
sudo gem install fakettp
Create a FakeTTP directory
You can install FakeTTP anywhere that your web server user can see it:
fakettp install <directory> <hostname>
Set hostname to the host you want to use for FakeTTP control requests (the examples below use fakettp.local
).
You can install multiple copies and run them independently by using different directories and hostnames (for example on a CI server to prevent clashes when building multiple projects in parallel).
Point your web server at the directory
FakeTTP should work with any Rack-compatible server: just point the server to the correct directory. For example, using Passenger (mod_rails) with Apache, create a virtual host along these lines:
<VirtualHost *:80>
ServerName fakettp.local
ServerAlias *.fake.local
DocumentRoot "/path/to/fakettp/public"
<directory "/path/to/fakettp/public">
Order deny,allow
Deny from all
Allow from 127.0.0.1
</directory>
</VirtualHost>
The ServerAlias
line means that FakeTTP will attempt to simulate all requests that match the supplied pattern. You can add as many of these as necessary.
Then make sure the simualtor hostname and any simulated hosts all resolve to 127.0.0.1 (assuming you’re running the simulator on the same machine as the application under test), eg by adding the following to /etc/hosts
:
127.0.0.1 fakettp.local
127.0.0.1 some-host.fake.local
IMPORTANT: security note
Because expectations are set by posting Ruby code to be executed on the server, you probably don’t want any old Tom, Dick or Harry to be able to connect. The security settings in the virtual host config example above restrict access to clients running on the local machine.
Usage
The examples below assume you’ve installed using the hostname fakettp.local
. If you’ve used a different host, adjust appropriately.
Resetting
To reset FakeTTP (ie remove all expectations and errors), make an HTTP POST request to http://fakettp.local/reset
.
Calling from curl
curl fakettp.local/reset -X POST
Setting expectations
To create a new expectation, make an HTTP POST request to http://fakettp.local/expect
, with a Content-Type header of ‘text/plain’ and the request data containing a Ruby block to execute.
The supplied code should be in the following format, and will generally consist of a number of assertions on the request, followed by creation of the response to return to the application under test.
expect "GET of /foo" do
request.host.should == 'fakettp.local'
request.path_info.should == '/foo'
content_type 'text/plain'
"All is well\n"
end
The label on the first line is used in error reporting.
The expectation code has access to the underlying Sinatra request and response objects etc, as well as RSpec matchers.
Calling from curl
Assuming the expectation is in expectation_file
:
curl -X POST fakettp.local/expect -X POST -H ‘Content-Type:text/plain’ –binary-data <expectation_file>
Verifying
To verify that all expectations have been met, make an HTTP GET request to http://fakettp.local/verify
.
If all is well, the response will be a 200 OK with a body of ‘OK’. Otherwise the status will be 400 Bad Request, with a list of failures in the body. The failure messages include the complete details of the unexpected request that was received, to assist debugging.
Calling from curl
curl fakettp.local/verify
Web console
Point your browser at fakettp.local/
Currently this is very basic, just showing the expectations from the last run. Expectations are colour-coded according to status, and any error messages are shown.
Multiple faked hosts
To have FakeTTP respond to multiple hostnames, create the appropriate hosts entries. If you’re using name-based virtual hosts in Apache, add a ServerAlias entry to the virtual host config, under the ServerName line, eg:
ServerAlias foo.com .com
Change log
0.3.7 (19 November 2009)
-
Show error messages in console.
-
Use nokogiri instead of hpricot for testing.
0.3.6 (3 November 2009)
-
Properly include rspec as a runtime dependency.
0.3.5 (3 November 2009)
-
Fixed Sinatra deprecation warnings from config.ru.
0.3.4 (2 november 2009)
-
Depend on release Sinatra instead of edge.
0.3.3 (29 October 2009)
-
Log to fakettp.log in installed directory.
-
Switch from Sinatra::Test to Rack::Test.
0.3.2 (19 October 2009)
-
Accidentally bumped version number twice :-(
0.3.1 (19 October 2009)
-
Added missing dependencies.
-
Allow specification of hostname on installation.
0.3.0 (19 May 2009)
-
Fixed some issues with multiple hosts
0.3.0 (18 May 2009)
-
Now uses SQLite and ActiveRecord to store expectations, instead of the filesystem.
-
Supports specification of hostname on installation
-
HTML page showing expectations from the last run
0.2.4.1 (5 May 2009)
-
Temporarily depend on edge version of Sinatra, to gain Rack 1.0 compatibility.
0.2.4 (25 Mar 2009)
-
Fixed a bug which caused expectations to be run in the wrong order if there
were more than nine of them.
0.2.3 (19 Mar 2009)
-
Fixed a bug where expectations were being overwritten on Linux due to Dir.entries not returning results in the expected order
0.2.2 (18 Mar 2009)
-
Only accept control requests (reset, expect, verify) on fakettp.local
0.2.1 (17 Mar 2009)
-
Fixed issue where rspec matchers weren’t available to expectations
0.2 (14 Mar 2009)
-
Complete rewrite, with tests and classes and stuff this time.
If you get an ‘unexpected return’ error, remove the return statement from your expectation, and just put the return value on the last line of the expect block.
0.1.2 (13 Feb 2009)
-
Make sure README.html appears in generated gem
0.1.1 (13 Feb 2009)
-
Fix permissions on installed tmp directory.
0.1.0 (13 Feb 2009)
-
First release as a gem.
To Do
-
Add examples
-
Make control requests RESTful?
-
Show label in verification error for expected requests that weren’t received
-
Add facility to stub as well as mock requests
-
Allow more flexibility in request ordering
-
Allow user-specific helper files in installation dir
-
Provide Ruby API to set expectations etc
-
Return the expected content type even if expectation fails
-
Highlight failed lines in console