Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rspec: run an outside rails server

This question is about starting a rails server of the external project from a rspec environment.

There is 2 projects.

  • First project act as the Admin Back Office, it's the central application where users interact with web pages. I call it BackOffice
  • Second project is a Json API Server which will receive commands from the Admin Back Office through json requests.I call it ApiServer

I am trying to test API interaction between those 2 rails projects, and I would like to set-up rspec so I can write and maintain my spec files in BackOffice project. Those specs would start a ApiServer rails server and then play around to perform the tests.

My issue is about starting the ApiServer rails server. After looking at the rails app initialization files, I assumed I had to add a require to "config/environment".


But when I insert into BackOffice/spec/spec_helper.rb

require File.expand_path('../../../ApiServer/config/environment', __FILE__)

I get the error

`initialize!': Application has been already initialized. (RuntimeError)
# Backtrace to the file:
# ApiServer/config/environment.rb
# Line:
# Rails.application.initialize!

I also tried to simply call the following in backticks

`cd /api/path; bundle exec rails s -p 3002` 

but got the same kind of error


Then I got inspiration from Capybara source code, and required the "ApiServer/application", then I am able to create a ApiServer.new object, but as soon as I call initialize! on it it I get the same message.

Any help is greatly appreciated. Cheers

like image 573
Benj Avatar asked Oct 19 '22 03:10

Benj


2 Answers

Actually the second app is nothing more then an external service, which is better to stub for the tests.

There is one nice article from thoughtbot about using vcr gem to mock external web services:

https://robots.thoughtbot.com/how-to-stub-external-services-in-tests

like image 75
Yury Lebedev Avatar answered Oct 27 '22 23:10

Yury Lebedev


Obligatory "don't do that unless you really need to".

However, since it seems you know what you need:

Short answer:

You need to isolate both application in system environment and launch it from there using system-calls syntax.

Long answer:

What you're trying to do is to run two Rails applications in the same environment. Since they both are Rails applications they share a lot of common names. Running them ends in name clash, which you're experiencing. Your hunch to try simple back ticks was good one, unfortunately you went with a bundler in already existing environment, which also clashes.

What you have to do in order to make it work is to properly isolate (in terms of code, not in terms of network i.e. communication layer ) application and then run launcher from rspec. There are multiple ways, you could:

  • Use Ruby process control (Check this graph, you could try to combine it with system level exec)
  • Daemonize from Operating System level (init.d etc.)
  • Encapsulate in VM or one of the wrappers (Virtualbox, Vagrant, etc.)
  • Go crazy and put code on separate machine and control it remotely (Puppet, Ansible, etc.)

Once there, you can simply run launcher (e.g. daemon init script or spawn new process in isolated environment) from RSpec and that's it.

Choosing which way to go with is highly dependent on your environment. Do you run OSX, Linux, Windows? Are you using Docker? Do you manage Ruby libraries through things like RVM? Things like this.

like image 44
XLII Avatar answered Oct 27 '22 23:10

XLII