pactum: one REST API testing library for the whole test pyramid
REST API Testing Tool for all levels in a Test Pyramid
At a glance
- What is it?
- pactum is a JavaScript library for automating e2e, integration, contract and component tests against HTTP APIs, with a fluent request builder, a data provider and a mock server that can run as a standalone simulator. It suits a Node team that wants one testing idiom across every layer, and it stops at the HTTP boundary, with no gRPC or WebSocket support.
- Who is it for?
- Adopt pactum if your team works on HTTP and HTTPS services in Node and wants one assertion style for component, contract, integration and e2e tests, plus a mock server for generating contracts. Do not adopt it for a gRPC or WebSocket estate, for load testing, or if you need a consumer-driven contract artefact rather than a simulator you configure in code.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 73 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One library for four layers of the test pyramid
PactumJS is a REST API testing tool used to automate e2e, integration, contract and component, or service level, tests. That sentence is the product in one line, and it is a differentiator: most teams end up with two or three different HTTP testing libraries, one for component tests written by the service team and another for end to end tests written by a QA team, and the assertion style diverges with them.
The feature list in the README is written as adjectives, and each one corresponds to a decision. Swift and lightweight, with a dependency list that is a dozen packages rather than a framework. Simple and powerful, in the sense that the API is a chain of descriptive methods rather than a configuration object. A compelling mock server, which is a separate feature rather than a side effect. Elegant data management, extendable and customizable, and a clear and comprehensive testing style.
The framing of the whole library is that the same spec object works at every level. A component test that runs a request against the service in your own process and a deployment level test that runs the same request against a deployed environment use the same builder and the same expectations, and the difference is the base URL. That is the reason to pick one library rather than several, and it is also the reason it is worth the trouble of learning the style once.
The documentation site at pactumjs.github.io has separate guides for API testing, integration testing, component testing, contract testing, e2e testing and the mock server, which tells you how the levels are meant to be used.
The spec builder is a chain of descriptive methods
The core object is the spec, and the style is a fluent chain. A test with Mocha looks like this:
const { spec } = require('pactum');
it('should be a teapot', async () => {
await spec()
.get('http://httpbin.org/status/418')
.expectStatus(418);
});
it('should save a new user', async () => {
await spec()
.post('https://jsonplaceholder.typicode.com/users')
.withHeaders('Authorization', 'Basic xxxx')
.withJson({
name: 'bolt',
email: '[email protected]'
})
.expectStatus(200);
});The structure is worth reading closely. The request side is get and post for the method, withHeaders for headers, withJson for a body. The expectation side is expectStatus, and the method names in the library follow that convention, expect something for a response assertion. The chain is accumulated state, and the final step performs the request and checks the expectations.
In the Cucumber integration, that split becomes explicit. The step definitions build the request, a separate step calls spec.toss() to perform it, and a third step asserts on the response with spec.response().should.have.status(code). So the same object that built the request is the one that holds the response, and the assertions read from it rather than from a separate return value.
The library is also usable without any test framework, since spec() is just an object. That is what makes it usable at the component level, where a service team runs a plain script rather than a test suite.
Installation, the test runner, and the init shortcut
The install is a dev dependency, because a testing library that ends up in your production dependency tree is a mistake:
# install pactum as a dev dependency
npm install --save-dev pactum
# install a test runner to run pactum tests
# mocha / jest / cucumber
npm install --save-dev mochaThe second command is the one people miss. pactum does not bring a test runner with it, and the documentation is explicit that you install one, with Mocha, Jest or Cucumber named as the options. The README shows the Mocha case, where the runner is invoked on a path:
# mocha is a test framework to execute test cases
mocha /path/to/testThere is also a shortcut for people who do not want to set anything up:
npx pactum-initFor BDD style work, the documentation points at a separate boilerplate repository, pactum-cucumber-boilerplate, for the details of the pactum and cucumber integration, and the step definitions in the README show the shape of that setup. The Given, When and Then steps are mapped onto the spec object, with a Before hook that creates a fresh spec for each scenario so that state does not leak between tests.
The manifest also states the runtime requirement, node 20.19 or later, which is worth checking before you add the dependency to a project that is still on an older long term support release.
The mock server is the same library, standing on its own
pactum can act as a standalone mock server that allows you to mock any server via HTTP or HTTPS, such as a REST endpoint. The description in the documentation calls it simply a simulator for HTTP-based APIs.
The API is a small DSL of its own. You add an interaction with the request you expect and the response you want to return, then start the server on a port:
const { mock } = require('pactum');
mock.addInteraction({
request: {
method: 'GET',
path: '/api/projects'
},
response: {
status: 200,
body: [
{
id: 'project-id',
name: 'project-name'
}
]
}
});
mock.start(3000);The value of that design is that the mock is defined in the same language and the same style as the tests that consume it, and that a service team can start a mock of an upstream dependency in a test without leaving the repository or installing a separate tool.
It is also the mechanism behind contract testing in this library. A consumer-side test can point at the mock, record the interactions, and use them to produce a contract for the provider. That is the same role the pact ecosystem plays with a different approach, and the README is explicit about the lineage: the project says it is inspired from frisby and from pact.
The dependency list tells you what the library does for you
The runtime dependencies in the manifest are small and each one points at a capability.
For matching and validation there is @exodus/schemasafe, which is a JSON schema validator, and pactum-matchers, the matcher set the library uses to assert on response bodies. For reaching into a response there is json-query, which is JSON path querying. For the open source world, openapi-fuzzer-core provides the fuzzing capability, and parse-graphql handles GraphQL documents.
For the server side of things, polka is the HTTP server the mock runs on, and phinx handles database migrations, which is what lets the library set up test data rather than assuming the database is already there. The smaller utilities are klona for deep cloning of request and response objects, deep-override for merging, component-type for type helpers, and cookie-lite and form-data-lite for the two payload shapes that the standard libraries make awkward in test code.
Two things stand out. The inclusion of a migration library means the library expects to be able to prepare a database state, which is a component testing habit rather than an e2e one. And the absence of a test runner dependency is the reason the second install command exists.
One limitation of the README is worth flagging: the feature list advertises elegant data management, but the readme does not describe the data provider or its templating rules, so the details live in the documentation site rather than here.
Where pactum stops being the right tool
Four limits are clear from the package itself and from what the documentation does not cover.
The first is the protocol boundary. Everything here is HTTP and HTTPS, with GraphQL handled as a payload format through parse-graphql. There is no gRPC and no WebSocket support in the dependency list, so a service estate that speaks gRPC or that needs a WebSocket handshake test needs a different tool for that part of the pyramid.
The second is that pactum is a testing library, not a load generator. It makes requests and asserts on them. If the problem you have is throughput or latency under load, that is a different category of tool, and the readme does not claim otherwise.
The third is the mock server's nature. It is a simulator you configure in code, running in the same process or as a small standalone server. It is excellent for generating a contract from the consumer side and for stubbing an upstream in a test, but it is not a network-level mock that can sit between two real services and rewrite traffic on the wire.
The fourth is the alternative that matters for contract testing. The pact approach produces a consumer-driven contract as a first class artefact that both sides agree on, and the contract lives in version control and is verified in both directions. pactum's mock server produces a contract from recorded interactions, which is a lighter weight approach and much easier to adopt inside an existing test suite, but the artefact is not the same thing and a team that has a provider side expecting a pact style contract has to check the format.
The project is inspired from frisby and from pact, and the readme says so, which is the honest way to place it: it takes the readable request style of the first and the mock server role of the second.
Maintenance, licence and the state of the project
The project is not archived, and the last push was on 2026-08-11. The release history is v3.9.1 on 2026-02-27, v3.9.0 on 2025-12-21 and v3.8.0 on 2025-07-03, so the published version moves in step with the work rather than on a fixed schedule.
The package is published as pactum with the main entry at ./src/index.js and the type definitions alongside at ./src/index.d.ts, and the published files list contains only the src directory. The types are shipped in the package rather than generated at publish time, which is worth noticing for a library that advertises a TypeScript style.
The licence is MIT, with the author listed as Anudeep. The repository has a CHANGELOG.md, a CODE_OF_CONDUCT.md and a CONTRIBUTING.md, and the README points at the contributing documentation and at the contributors graph.
Support runs through GitHub Discussions rather than the issue tracker, which is a sensible split for a library with a lot of how do I questions, and the README badge points to a DeepWiki page for the project as another place to read about it. The documentation site is the canonical reference, and the README itself is explicitly described as a basic introduction, with a link to the full guides for each level of the pyramid.
Editorial conclusion
Adopt pactum if your team works on HTTP and HTTPS services in Node and wants one assertion style for component, contract, integration and e2e tests, plus a mock server for generating contracts. Do not adopt it for a gRPC or WebSocket estate, for load testing, or if you need a consumer-driven contract artefact rather than a simulator you configure in code. Verify first that your Node version is at least 20.19, that the matcher set covers the response shapes you assert on, and that the contract format the mock server produces is one your consumer side can consume.
Frequently asked questions
How do I install pactum and run a first test?
Install it as a dev dependency with npm install --save-dev pactum, install a test runner such as Mocha, Jest or Cucumber, and run the suite with mocha /path/to/test. The npx pactum-init command is offered as a shortcut for the setup.
What test levels does pactum support?
It is described as a REST API testing tool used to automate e2e, integration, contract and component, or service level, tests, and the documentation site has a separate guide for each of API, integration, component, contract and e2e testing plus the mock server.
How does the pactum mock server work?
You add an interaction with the expected request and the response to return using mock.addInteraction, and then start it with mock.start(3000). It can mock any server over HTTP or HTTPS and runs as a standalone simulator, which is also how contracts are generated for contract testing.
Which Node version does pactum need?
The package manifest declares node 20.19 or later. The published version is 3.9.1, released on 2026-02-27, and the last push to the repository was on 2026-08-11.
How does pactum compare with pact and frisby?
The README states that the project is inspired from frisby and from pact. It takes the readable request building style and adds a mock server that can run standalone and record interactions for contracts, rather than producing a consumer-driven contract artefact as the pact approach does.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pactumjs-pactum)Was this useful?