Description
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