Home > Software engineering >  no method error "merge" in Rails middleware
no method error "merge" in Rails middleware

Time:06-10

Hi I am building a Rails/Rack middleware for the Mailgun api, and doing a simple test for connection, which is fine in Postman with exact same params.

It is showing an error in test, Failure/Error: @app.call(env)

 NoMethodError:
   undefined method `merge!' for #<Mailgun::Tracking::MailLogger:0x0000557e6bc8bb50>

on running RSpec, and no merge method is attempted at all, so dont know where its come from. The api_key and endpoint are initialized in config/initialisers folder as per the Mailgun Tracking gem (which is being used) guidelines.

Only two other files used and code below.

MailLogger class under Mailgun::Tracking module, registered as middleware in app.

require 'logger'
require 'mailgun/tracking'
require 'rack/contrib'
require 'rack'
require 'byebug'

module Mailgun::Tracking
  class MailLogger
    def initialize(app, options = {
    "HTTP_X_MAILGUN_API_KEY" => ENV['MAILGUN_API_KEY'],
    "HTTP_X_MAILGUN_ENDPOINT" => ENV['MAILGUN_ENDPOINT']
    })
    @app = app
    @options = options
    end

    def call(env)
    @app.call(env)
    end
  end 
end

The RSpec test

require 'logger'
require "json"
require "rails_helper"
Bundler.require(*Rails.groups)
require_relative "../../lib/middleware/mailgun/mailgun_tracking.rb"

RSpec.describe Mailgun::Tracking::MailLogger, type: 'Mailgun Webhook' do
  subject(:response) { app.call(env) }
  # env to pass in middleware, url endpoint & key
  let(:app) { described_class.new(Rails.application) }
  let(:env) { described_class.new(app, options = {
   "HTTP_X_MAILGUN_API_KEY" => ENV['MAILGUN_API_KEY'],
    "HTTP_X_MAILGUN_ENDPOINT" => ENV['MAILGUN_ENDPOINT']
  }) }

 it "returns a 200 status code" do
    expect(response).to eq([200, {}, ["OK"]])
  end
end

Am just looking for a 200, OK on connection, as I already get in Postman with the same header (api_key) and endpoint (events)

but throws this mysterious missing "merge" method error

Not encountered before.

Anyone know why?

Thanks

CodePudding user response:

The actual code calling merge! is hidden in rack implementation and as such is filtered out from the error message. Your problem is that env you define in your test is not an instance of Rack::Environment but rather instance of your middleware. You can generate mocked environment instance using, for example, Rack::MockRequest.env_for("/", method: :get)

That being said, your unit test is currently testing the whole of the rack stack, including the routes and other middlewares. You can isolate your test better by using a mock application:

let(:app) { described_class.new(->(env) [200, {}, 'success']) }
  • Related