Testing in Base
Jest plus worker-shaped helpers, and the two altitudes every healthy test suite is built from.
Testing in Base
A framework that makes the right thing easy should make testing the right thing easy too. Base runs on Jest, and it gives you the supporting pieces you need to test a worker the way it actually runs: not by mocking the framework out, but by standing up the worker and talking to it. This post is the overview of how testing fits together in Base. The two posts that follow go deeper on testing a module in isolation and on full integration tests.
Jest, with worker-shaped helpers
Tests in Base are Jest tests. You write describe and test blocks, you expect things, you run the suite the way you run any Jest suite. Base does not replace your test runner; it sits on top of it and adds the parts that are specific to testing a worker.
The most important of those parts is a test environment. Base provides a test environment object that knows how to bring up the world a test needs and hand you a client to talk to the worker under test. Instead of each test file reinventing how to reach the server, set up transport, and tear down afterward, you reach for the shared environment and ask it for a client. That keeps test files small and focused on the behavior they are checking rather than on plumbing.
Two altitudes of test
Base supports testing at two altitudes, and knowing which you want is most of writing a good test.
The first is the unit and module altitude: testing a piece of your code, a service, a validator, a transform, in isolation, without standing up a live server. This is fast and tight, and it is where most of your tests should live. You test the logic where the logic is, with the smallest amount of the framework involved.
The second is the integration altitude: standing up the worker and exercising it end to end over its real surface, an HTTP route, a GraphQL operation, an RPC call. This is slower but truer: it checks that the decorators, the routing, the serialization, and the wiring all actually work together, not just that each piece works alone. The example worker's integration tests do exactly this, hitting real routes and asserting on real responses.
A healthy suite has many of the first and a meaningful layer of the second. The fast tests catch most mistakes in milliseconds; the integration tests catch the wiring mistakes that only show up when the pieces meet.
The client is the key
The thing that makes integration testing pleasant in Base is the test client. Rather than constructing raw requests, you get a client off the test environment that knows how to send HTTP requests, run GraphQL operations, and make RPC calls against the worker under test. So an integration test reads like a small program that uses your worker, because that is what it is: get the client, call the worker, assert on what comes back.
The mental model to keep
Testing in Base is Jest plus worker-shaped helpers: write ordinary Jest tests, lean on the test environment to bring up the world and hand you a client, and test at two altitudes. Keep most tests fast and isolated at the unit and module level, and add a layer of integration tests that stand up the worker and exercise its real surface through the test client. The next two posts go deep on each altitude.