tristandunn / pusher-fake

A fake Pusher server for development and testing.
https://rubygems.org/gems/pusher-fake
MIT License
173 stars 32 forks source link

Connection refused when running RSpec tests with Zeus #34

Closed Domon closed 8 years ago

Domon commented 10 years ago

Hi,

I have a problem that when running RSpec tests with Zeus, the tests pass in the first time, but failed from the second time.

The following is the error and backtrace:

Pusher::HTTPError:
  Connection refused - connect(2) for "127.0.0.1" port 61905 (Errno::ECONNREFUSED)
# .../gems/pusher-0.11.3/lib/pusher/request.rb:47:in `rescue in send_sync'
# .../gems/pusher-0.11.3/lib/pusher/request.rb:27:in `send_sync'
# .../gems/pusher-0.11.3/lib/pusher/resource.rb:18:in `post'
# .../gems/pusher-0.11.3/lib/pusher/client.rb:134:in `post'
# .../gems/pusher-0.11.3/lib/pusher/client.rb:216:in `trigger'
...

My guess is the thread of the fake server ends when the first run complete, so in the second run there are no fake server responding.

I wonder if this problem could be fixed by adding some configuration to RSpec or Zues, or it needs some modification in pusher-fake.

Any help or suggestion is appreciated. :smile:

tristandunn commented 10 years ago

I think you might be able to create a custom plan for Zeus to tell it when to run the server. I'm not familiar enough with that to provide an example. I might be able to poke around at some point in the future, but no promises. If there's anything I can do in pusher-fake to simplify it though, let me know.

Oh, one random idea. Determine if the server is running before the RSpec suite runs and start it if it isn't. That might be worth setting up in the included support files, if possible and it works.

gogoac commented 9 years ago

We ran into this as well. A custom plan did the trick for us:

# custom_plan.rb
require 'zeus/rails'

class CustomPlan < Zeus::Rails
  def test_environment
    Bundler.require(:test)

    ::Rails.env = ENV['RAILS_ENV'] = 'test'
    require APP_PATH

    $rails_rake_task = 'yup' # lie to skip eager loading
    ::Rails.application.require_environment!
    $rails_rake_task = nil

    $LOAD_PATH.unshift ".", "./lib", "./test", "./spec"

    ENV['ZEUS_TEST'] = 'zeus_test'

    # from pusher-fake/support/base
    PusherFake.configure do |configuration|
      configuration.app_id = Pusher.app_id
      configuration.key    = Pusher.key
      configuration.secret = Pusher.secret
    end
    PusherFake.configuration.web_options.tap do |options|
      Pusher.host = options[:host]
      Pusher.port = options[:port]
    end
    # Don't kill the server at_exit, since each zeus test exits.
    fork { PusherFake::Server.start }
  end
end

Zeus.plan = CustomPlan.new

This leaves the fake server running for repeated tests. Zeus itself seems to be kind enough to clean up the server when we actually stop the test environment.

With this custom plan, spec_helper.rb needs to be changed a little differently to run correctly with or without zeus.

# spec/spec_helper.rb
require 'pusher-fake/support/base' unless ENV['ZEUS_TEST']

RSpec.configure do |config|
  config.after(:each) do
    PusherFake::Channel.reset
  end
end
tristandunn commented 9 years ago

Awesome!

I think you can call super to avoid duplicating the test_environment method, hopefully saving some headaches from any future changes. And from a quick search I think you can use ZEUS_MASTER_FD instead of setting a custom ENV variable, but not 100% that's reliable.

It's not quite there for me when trying it with my Cucumber example. But I've been wanting to convert tristandunn/pusher-fake-example over to RSpec, so I might mess around with adding a Zeus support file as well, to make this even easier and provide a concise example.

Domon commented 9 years ago

It works. Thanks @gogoac! :smile:

I have modified the solution a bit to the following, as per @tristandunn's suggestion:

# custom_plan.rb

require 'zeus/rails'

class CustomPlan < Zeus::Rails

  def test_environment
    super

    #
    # Copied from pusher-fake/support/base.rb
    #

    # Use the same API key and secret as the live version.
    PusherFake.configure do |configuration|
      configuration.app_id = Pusher.app_id
      configuration.key    = Pusher.key
      configuration.secret = Pusher.secret
    end

    # Set the host and port to the fake web server.
    PusherFake.configuration.web_options.tap do |options|
      Pusher.host = options[:host]
      Pusher.port = options[:port]
    end

    #
    # Modified from pusher-fake/support/base.rb
    #

    # Start the fake socket and web servers, but don't kill the server at_exit.
    fork { PusherFake::Server.start }
  end

end

Zeus.plan = CustomPlan.new
# spec/spec_helper.rb

RSpec.configure do |config|

  #
  # Copied from pusher-fake/support/rspec.rb
  #

  require "pusher-fake/support/base" unless ENV["ZEUS_MASTER_FD"]

  config.after(:each) do
    PusherFake::Channel.reset
  end
end