Skip to main content
The Test Utilities module provides a comprehensive set of tools for testing AdonisJS applications. It includes utilities for creating HTTP contexts, starting test servers, and managing cookies during tests.

Import

import { TestUtils } from '@adonisjs/core/test_utils'

TestUtils Class

The main class for managing test utilities in AdonisJS applications.

Constructor

Create a new TestUtils instance.
app
ApplicationService
required
The application service instance
import { TestUtils } from '@adonisjs/core/test_utils'

const testUtils = new TestUtils(app)
await testUtils.boot()

Properties

app

Reference to the application service instance.
app
ApplicationService
The application service passed to the constructor
const app = testUtils.app

cookies

Cookie client instance for handling cookies in tests.
cookies
CookieClient
Instance for managing cookies during testing
const encrypted = testUtils.cookies.encrypt('session_data')
const decrypted = testUtils.cookies.decrypt(encrypted)

isBooted

Check if test utils have been booted.
isBooted
boolean
Returns true if boot() has been called
if (!testUtils.isBooted) {
  await testUtils.boot()
}

Methods

boot

Boot the test utilities. This must be called before using other methods. Returns: Promise<void>
const testUtils = new TestUtils(app)
await testUtils.boot()
The application must be booted and the container must have all bindings before calling this method.

createHttpContext

Create an HTTP context for testing.
options
object
Optional configuration for creating HTTP context
options.req
IncomingMessage
Custom Node.js IncomingMessage instance
options.res
ServerResponse
Custom Node.js ServerResponse instance
Returns: Promise<HttpContext> - HTTP context instance for testing
// Create a default context
const ctx = await testUtils.createHttpContext()

// Create context with custom request/response
import { IncomingMessage, ServerResponse } from 'node:http'
import { Socket } from 'node:net'

const req = new IncomingMessage(new Socket())
const res = new ServerResponse(req)
const ctx = await testUtils.createHttpContext({ req, res })

// Use the context in tests
ctx.request.method = 'POST'
ctx.request.url = '/users'

httpServer

Get an instance of HTTP server testing utilities. Returns: HttpServerUtils - Instance for managing test HTTP server
const httpUtils = testUtils.httpServer()
const closeServer = await httpUtils.start()

// Make HTTP requests to test endpoints
// ...

await closeServer()

Usage Example

import { test } from '@japa/runner'
import { TestUtils } from '@adonisjs/core/test_utils'

test.group('Users', (group) => {
  let testUtils: TestUtils
  
  group.setup(async () => {
    testUtils = new TestUtils(app)
    await testUtils.boot()
  })
  
  test('can create http context', async ({ assert }) => {
    const ctx = await testUtils.createHttpContext()
    assert.exists(ctx.request)
    assert.exists(ctx.response)
  })
})

HttpServerUtils Class

Utilities for starting and stopping the AdonisJS HTTP server during testing.

Constructor

Creates a new HttpServerUtils instance.
utils
TestUtils
required
The test utils instance
const httpUtils = testUtils.httpServer()
You typically don’t create this directly. Use testUtils.httpServer() instead.

Methods

start

Start the HTTP server for integration testing.
serverCallback
function
Optional callback to create a custom HTTP server instance
handler
(req: IncomingMessage, res: ServerResponse) => any
The request handler function
Returns: NodeHttpsServer | NodeHttpServer - Custom server instance
Returns: Promise<() => Promise<void>> - Function to close the server
import { test } from '@japa/runner'
import supertest from 'supertest'

test.group('API Tests', (group) => {
  let closeServer: () => Promise<void>
  
  group.setup(async () => {
    const httpUtils = testUtils.httpServer()
    closeServer = await httpUtils.start()
  })
  
  group.teardown(async () => {
    await closeServer()
  })
  
  test('GET /users returns 200', async () => {
    const response = await supertest(process.env.HOST)
      .get('/users')
      .expect(200)
  })
})

Using with HTTPS

import https from 'node:https'
import fs from 'node:fs'

const options = {
  key: fs.readFileSync('test-key.pem'),
  cert: fs.readFileSync('test-cert.pem')
}

const closeServer = await httpUtils.start((handler) => {
  return https.createServer(options, handler)
})

Environment Variables

The HTTP server uses the following environment variables:
HOST
string
default:"0.0.0.0"
The host address to bind the server to
PORT
string
default:"3333"
The port number to listen on
# .env.test
HOST=127.0.0.1
PORT=4000

CookieClient

The CookieClient class is available through testUtils.cookies and provides methods for encrypting and decrypting cookies.

encrypt

Encrypt a cookie value.
value
string
required
The cookie value to encrypt
Returns: string - Encrypted cookie value
const encrypted = testUtils.cookies.encrypt('user_session_data')

decrypt

Decrypt a cookie value.
value
string
required
The encrypted cookie value to decrypt
Returns: string - Decrypted cookie value
const decrypted = testUtils.cookies.decrypt(encryptedValue)

sign

Sign a cookie value.
value
string
required
The cookie value to sign
Returns: string - Signed cookie value
const signed = testUtils.cookies.sign('remember_token')

unsign

Unsign and verify a signed cookie.
value
string
required
The signed cookie value to verify and unsign
Returns: string | null - Unsigned value if valid, null if invalid
const unsigned = testUtils.cookies.unsign(signedValue)
if (unsigned) {
  console.log('Valid cookie:', unsigned)
}

Testing Examples

Basic HTTP Context Testing

import { test } from '@japa/runner'

test('middleware sets user on context', async ({ assert }) => {
  const ctx = await testUtils.createHttpContext()
  
  // Simulate request
  ctx.request.method = 'GET'
  ctx.request.url = '/profile'
  
  // Run middleware
  await authMiddleware.handle(ctx, async () => {})
  
  assert.exists(ctx.auth.user)
})

Integration Testing with HTTP Server

import { test } from '@japa/runner'
import supertest from 'supertest'

test.group('User API', (group) => {
  let closeServer: () => Promise<void>
  let baseUrl: string
  
  group.setup(async () => {
    const testUtils = new TestUtils(app)
    await testUtils.boot()
    
    const httpUtils = testUtils.httpServer()
    closeServer = await httpUtils.start()
    
    baseUrl = `http://${process.env.HOST}:${process.env.PORT}`
  })
  
  group.teardown(async () => {
    await closeServer()
  })
  
  test('can register new user', async ({ assert }) => {
    const response = await supertest(baseUrl)
      .post('/register')
      .send({ email: 'test@example.com', password: 'secret' })
      .expect(201)
    
    assert.exists(response.body.id)
  })
  
  test('can login user', async ({ assert }) => {
    const response = await supertest(baseUrl)
      .post('/login')
      .send({ email: 'test@example.com', password: 'secret' })
      .expect(200)
    
    assert.exists(response.body.token)
  })
})

Testing with Cookies

import { test } from '@japa/runner'

test('can encrypt and decrypt session cookie', async ({ assert }) => {
  const testUtils = new TestUtils(app)
  await testUtils.boot()
  
  const sessionData = JSON.stringify({ userId: 1, role: 'admin' })
  const encrypted = testUtils.cookies.encrypt(sessionData)
  const decrypted = testUtils.cookies.decrypt(encrypted)
  
  assert.equal(decrypted, sessionData)
})

test('can sign and verify remember token', async ({ assert }) => {
  const testUtils = new TestUtils(app)
  await testUtils.boot()
  
  const token = 'abc123'
  const signed = testUtils.cookies.sign(token)
  const unsigned = testUtils.cookies.unsign(signed)
  
  assert.equal(unsigned, token)
})

Testing Route Handlers

import { test } from '@japa/runner'

test('users controller returns user list', async ({ assert }) => {
  const ctx = await testUtils.createHttpContext()
  const controller = await app.container.make(UsersController)
  
  await controller.index(ctx)
  
  assert.equal(ctx.response.getStatus(), 200)
  assert.isArray(ctx.response.getBody())
})

Best Practices

  1. Always boot test utils before using them:
    const testUtils = new TestUtils(app)
    await testUtils.boot()
    
  2. Clean up servers after tests:
    group.teardown(async () => {
      await closeServer()
    })
    
  3. Use environment variables for test configuration:
    // .env.test
    HOST=127.0.0.1
    PORT=4000
    NODE_ENV=test
    
  4. Isolate test data by using transactions or cleaning up after each test:
    group.each.setup(async () => {
      await Database.beginGlobalTransaction()
    })
    
    group.each.teardown(async () => {
      await Database.rollbackGlobalTransaction()
    })
    
  5. Reuse test utils across test groups when possible:
    // tests/bootstrap.ts
    export const testUtils = new TestUtils(app)
    
    // tests/users.spec.ts
    import { testUtils } from './bootstrap.ts'