Rails testing with static server
I wanted to test some part of my application that performs HTTP requests against a different website. Now, for testing, I didn’t want to perform actual outside HTTP calls because they tend to become flaky if the internnet becomes unstable or when the remote resource is not available. Another reason, why I didn’t want to use the rails server and their static files, is that I didn’t want to serve those files in production. So I decided to write my own static file server.
Requirements
The requirements are quite simple. I wanted something that I can spin up from Ruby in the current process and that is able to serve static files from a predefined folder. For this purpose, I created afiles
folder under fixtures
. The other requirement is that I did not want it to clash with any other server that might be running on the target system. The reason is that I am planning to run this on my CI pipeline and I have very little control over what runs there. Furthermore, if tests run in parallel I didn’t want to spend much time on synchronization, instead spin up a temporary server for each test and shut it down immediately afterwards.
Solution
I came up with two methods that I added to thetest_helper.rb
in my Rails application: fixture_server
and replace_port!
. The former starts a server and returns the instance of the server itself, giving full control over the server process, including shutdown. This is intended if the server should run for a whole suite instead of for a single test. The block mode allows to start a server inline, and end it immediately. This mode is intended for cases when only a single tests uses the server. See the following example for example usage.
As the port number is dynamic, the HTTP calls also need to be constructed dynamically. I found that it is relatively easy to write <PORT>
in my URLs and then use the small helper method replace_port!
to replace the port via regular expression inline.
The complete code for the methods fixture_server
and replace_port!
is listed below. The dynamic port number is achieved by passing 0
. This tells the system to use the first available port. The server is started in a different thread to be non-blocking and automatically shuts down upon receiving a SIGINT
signal.
Besides the installation of the webrick
gem, that is all that is needed to serve static files during tests in Rails from the fixtures/files
folder.