---
title: How to Fix Circular Dependency Errors in Rails Integration Tests
teaser: Turn off concurrency in tests to avoid race conditions in Capybara.
tags: web,rspec,rails,testing,capybara,angularjs
author: Cameron Cundiff
published_on: 2014-11-28
---

We recently joined an existing Rails 4.1 project that uses AngularJS. We
observed sporadic `Capybara::ElementNotFound` failures in RSpec feature specs
with JavaScript. These failures were false positives and undermined our
confidence in the test suite, preventing us from using a fluid outside-in
testing process.

## Finding the Problem

We saw in Capybara screenshots that the pages (rendered with AngularJS) were
failing to fully load, but only in tests. In order to learn more, we reviewed
`test.log`, and saw this error:

    RuntimeError (Circular dependency detected while autoloading constant MyClass)

This looked like a race condition while loading files. [Lazily loading files is
not threadsafe in Ruby](http://m.onkey.org/thread-safety-for-your-rails), and
since Webrick is multithreaded and `Rails.configuration.eager_loading` is
disabled by default in test, we suspected that concurrency was enabled.

In production environments, Rails 4.1 uses `Rack::Lock` if classes won't be
cached (true in development by default, but false in production by default).
`Rack::Lock` creates a mutex around requests that guards against threadsafety
issues in multithreaded environments such as Webrick (the test server). We
expected that `Rack::Lock` would be used in tests as well, but to make sure we
ran `RAILS_ENV=test rake middleware`, and saw that `Rack::Lock` was missing.

## The Crux

The reason we were seeing the circular dependency error was that Capybara was
making many concurrent requests to a multithreaded server (Webrick) with
`Rack::Lock` disabled. This became an especially insidious problem in an
AngularJS app, given the number of concurrent requests being triggered via AJAX.

## The Solution

We concluded that we needed to force `Rack::Lock` middleware to be added in
test. This was echoed in [this Rails
issue](https://github.com/rails/rails/commit/112077c255879351edf4530791cc4bcc7bd4005b)
raised on GitHub.

Rails adds `Rack::Lock` unless `allow_concurrency` is true. It follows that we
can explicitly set `allow_concurrency` to false in our test environment to force
`Rack::Lock` to be added.

```ruby
# config/test.rb
config.allow_concurrency = false
```

The issue will be [fixed in Rails
4.2](https://github.com/rails/rails/commit/112077c255879351edf4530791cc4bcc7bd4005b),
but in the interim, explicitly disabling concurrency has fixed the circular
dependency error we were seeing.

Practicing Red/Green/Refactor and outside-in testing depends on getting reliable
failures from the tests, and we didn't have that. Resolving flakiness in the
test suite thus made a notable improvement in our <abbr title="Test Driven
Development">TDD</abbr> workflow while reviving confidence in the tests.
