Skip to content

08 - Testing and Local Debugging (Flex Consumption)

Test your Node.js v4 handlers in isolation, mock the invocation context and bindings, run local integration tests against Azurite, and attach the Node inspector for breakpoint debugging.

Prerequisites

Tool Minimum version Purpose
Node.js 20 LTS Run function code and tests
Azure Functions Core Tools 4.x Local host and debugging
Jest or Vitest Latest Test runner
Azurite 3.x Local Azure Storage emulator
Visual Studio Code Latest Breakpoint debugging (optional)

What You'll Build

You will add a test suite to the Flex Consumption app that unit-tests an HTTP handler, mocks the InvocationContext, runs an integration test against Azurite, and attaches the Node inspector to a running host.

1. Unit Test the Handler

In the v4 model a handler is a plain async function, so it tests cleanly. Keep logic separate from the trigger registration.

// src/logic.js
export function buildGreeting(name) {
  return `Hello, ${(name ?? "world").trim()}!`;
}
// src/functions/hello.js
import { app } from "@azure/functions";
import { buildGreeting } from "../logic.js";

export async function hello(request, context) {
  const name = request.query.get("name");
  return { status: 200, body: buildGreeting(name) };
}

app.http("hello", { methods: ["GET"], authLevel: "function", handler: hello });
// test/logic.test.js
import { buildGreeting } from "../src/logic.js";

test("buildGreeting trims and formats", () => {
  expect(buildGreeting("  ada ")).toBe("Hello, ada!");
});
npm install --save-dev jest
npx jest

2. Mock the Invocation Context and Request

Build lightweight fakes for HttpRequest and InvocationContext to exercise the handler directly.

// test/hello.test.js
import { hello } from "../src/functions/hello.js";

function fakeRequest(query = {}) {
  return { query: new Map(Object.entries(query)) };
}

function fakeContext() {
  return { log: () => {}, error: () => {}, invocationId: "test-1" };
}

test("hello returns a greeting", async () => {
  const res = await hello(fakeRequest({ name: "grace" }), fakeContext());
  expect(res.status).toBe(200);
  expect(res.body).toBe("Hello, grace!");
});

Keep the handler exportable

Export the handler function separately from the app.http(...) registration so tests can import it without booting the Functions host.

3. Integration Test Against Azurite

Azurite emulates Blob, Queue, and Table storage locally.

npm install -g azurite
azurite --silent --location ./.azurite &
{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "node"
  }
}
// test/queue.integration.test.js
import { QueueServiceClient } from "@azure/storage-queue";

const CONN = "UseDevelopmentStorage=true";

test("queue roundtrip against Azurite", async () => {
  const svc = QueueServiceClient.fromConnectionString(CONN);
  const queue = svc.getQueueClient("work-items");
  await queue.createIfNotExists();
  await queue.sendMessage(Buffer.from("job-42").toString("base64"));
  const msgs = await queue.receiveMessages();
  expect(Buffer.from(msgs.receivedMessageItems[0].messageText, "base64").toString()).toBe("job-42");
  await queue.deleteIfExists();
});

4. Breakpoint Debugging with the Node Inspector

Start the host with the inspector enabled:

func start --node-inspect

Attach from VS Code with .vscode/launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Attach to Node Functions",
      "type": "node",
      "request": "attach",
      "port": 9229
    }
  ]
}

Set a breakpoint in hello, attach, then call http://localhost:7071/api/hello?name=ada.

Flex Consumption note

Testing and debugging run entirely on your local machine and are identical across hosting plans. The Flex Consumption plan changes only how the deployed app scales and networks.

Verification

  • [ ] npx jest reports all tests passing.
  • [ ] The Azurite integration test round-trips a queue message without a real storage account.
  • [ ] A VS Code breakpoint in hello is hit when you invoke the local endpoint.

Next Steps

See Also

Sources