Search code examples
rubymongodbasynchronouseventmachinegoliath

How to test em-mongo + Goliath?


This below app saves some data to the db and I want to test that it saves properly.

require 'goliath'

class App < Goliath::API
  def response(env)
     db = EM::Mongo::Connection.new('localhost').db('hello')
     db.collection('coll').insert({'identifier => 1'})

    [204, {}, {}]
  end
end

require 'goliath/test_helper'    
Goliath.env = :test

describe App do
  include Goliath::TestHelper

  it do
    with_api(described_class) do
      get_request do |req|
        db = EM::Mongo::Connection.new('localhost').db('hello')
        db.collection('coll').first.callback do |rec|
          rec['identifier'].should == 100
        end
      end
    end
  end
end

The above spec passes since reactor ends before callback returns. I thought about manually starting a reactor like:

EM.run do
  db = EM::Mongo::Connection.new('localhost').db('hello')
  db.collection('coll').first.callback do |rec|
    rec['identifier'].should == 100

    EM.stop
  end
end

Though I'm not sure if starting the reactor for every spec is good practice. Help please?


Solution

  • The problem is that when the get_request is setup we add a callback on the request that stops the event loop. So, as soon as your block finishes (which will be before the connection is even created), it will stop the reactor.

    I'm not sure the best solution, but a crappy one would be to override:

    def hookup_request_callbacks(req, errback, &blk)
      req.callback &blk
      req.callback { stop }
    
      req.errback &errback if errback
      req.errback { stop }
    end
    

    in your test class after you include Goliath::TestHelper. Then, I think, you should be able to write your own that just has something like:

    def hookup_request_callbacks(req, errback, &blk)
      req.callback &blk
    
      req.errback &errback if errback
      req.errback { stop }
    end
    

    You'll just have to make sure you call stop in your callback from Mongo.

    I haven't actually tested this, so let me know if something doesn't work and I can dig in further.