8000 No defined way to test composition of middleware · Issue #48 · gocardless/coach · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
No defined way to test composition of middleware #48
Open
@nickcampbell18

Description

@nickcampbell18

Problem

Let's say I have a large application, with many middleware. Some middleware are simply composition units of others, for example:

class Middleware::Authenticate
  uses Middleware::ExtractBearerToken
  uses Middleware::LookupBearerToken
  uses Middleware::LogBearerToken

  requires :bearer_token
  provides :user

  def call
    provide(user: bearer_token.user)
    next_middleware.call
  end
end

I think this is a use-case which isn't currently tested well:

  • We have boot-time checking of the dependency tree (so we check that ExtractBearerToken provides :bearer_token)
  • We have unit tests of each sub-middleware behaving in the correct way in isolation.
  • We have request specs testing the overall route (including interactions of all the other middleware).

But there doesn't seem to be a simple way of saying, in a test, "run this smaller middleware chain" (i.e. invoke each sub-middleware and then run Middleware::Authenticate#call). The behaviours of this unit might vary depending on inputs/outputs of each sub-middleware in a way which isn't best expressed in isolated unit tests nor in the high-level request specs (which can be slow).

I think that endorsing this kind of testing to uncover interaction edge-cases would be incredibly valuable.

Proposal

Add a high-level API, either to coach/rspec or in the README, for running a full middleware chain like this.

The usage would look something like:

describe Middleware::Authenticate do
  subject(:instance) { Coach::Chain.new(described_class) } # this is the interesting bit
  
  it { is_expected.to call_next_middleware }
  it { is_expected.to provide(user: ...) }

  context "when a bearer token isn't in the request" do
    it "bails out before calling the main function"
  end
end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0