CodeOath
← All posts
Architecture & Patterns50 min total · 13 parts

Middleware Pipelines Compared: ASP.NET Core, Express.js, and Django

Part 12 of 13 · ~1 min

Testing Middleware Without Standing Up a Server

None of Counter's middleware needs a live server or an actual route to test, since underneath each one is nothing more than a function — or a small class — wrapped around a stand-in for "whatever comes next":

def test_store_closed_blocks_writes_during_reconciliation():
    def get_response(request):
        return HttpResponse("should not be reached")

    middleware = StoreClosedMiddleware(get_response)
    with mock_reconciliation_window(active=True):
        response = middleware(fake_post_request("/returns/4471/approve"))

    assert response.status_code == 503
test("requireManager rejects an associate approving over the threshold", () => {
  const req = { user: { isShiftLead: false }, body: { amountCents: 98000 } };
  const res = { status: jest.fn().mockReturnThis(), json: jest.fn() };
  const next = jest.fn();

  requireManager(req, res, next);

  expect(res.status).toHaveBeenCalledWith(403);
  expect(next).not.toHaveBeenCalled(); // confirms the chain actually stopped here
});
[Fact]
public async Task ApprovalAuditMiddleware_LogsStatusCode_ForApprovalRoute()
{
    RequestDelegate next = ctx => { ctx.Response.StatusCode = 200; return Task.CompletedTask; };
    var middleware = new ApprovalAuditMiddleware(next);
    var context = new DefaultHttpContext();
    context.Request.Path = "/returns/4471/approve";
    context.Request.Method = "POST";

    await middleware.InvokeAsync(context);

    Assert.Equal(200, context.Response.StatusCode); // next() actually ran, unmodified
}

Notice the three tests above do the identical thing, just spelled in three different languages: substitute something fake for "whatever's downstream" — a stub get_response, a mock next, a bare RequestDelegate lambda — invoke the middleware on its own, and confirm whether that stand-in got reached. Pass-through versus stop is the entire vocabulary this pattern speaks, which means it's also the entire surface area worth writing an assertion against.