SuperAPI AI Directory

testing

Testing & quality

View repository

Updated 10-16 09:47

About this skill

Testing — CAP Best Practices

Primary reference: https://cap.cloud.sap/docs/node.js/cds-test Vitest support (primary): https://cap.cloud.sap/docs/releases/2026/apr26

Recommended test runner: Vitest (CAP April 2026+)

cds.test now fully supports Vitest as a primary choice, while still maintaining compatibility with other test runners like Jest, Mocha, or Node's built-in test runner. Vitest is fully ESM compatible and recommended because Chai v6 (ESM) can no longer be fully provided in Jest runs — cds.test only provides a partial Chai emulation in Jest.

CDS 10+: New CAP projects are ESM-based by default ("type": "module" in package.json). Use import syntax in test files. To create a CommonJS project, remove "type": "module" from package.json.

npm install --save-dev @cap-js/cds-test vitest

vitest.config.js:

import { defineConfig } from 'vitest/config'
export default defineConfig({
  test: {
    testTimeout: 30000,
    hookTimeout: 30000,
  }
})

package.json:

{
  "scripts": {
    "test": "vitest run"
  }
}

Basic integration test

// tests/catalog.test.js
import cds from '@sap/cds'
const { GET, POST, DELETE, expect } = cds.test('.')

describe('CatalogService', () => {
  it('lists products', async () => {
    const { data } = await GET('/catalog/Products')
    expect(data.value).to.be.an('array')
    expect(data.value.length).to.be.greaterThan(0)
  })

  it('rejects order with negative quantity', async () => {
    const res = await POST('/catalog/submitOrder', {
      product: '2b23bb4b-4ac7-4a24-ac02-aa10cabd842c',
      quantity: -1
    })
    expect(res.status).to.equal(422)
  })
})

Testing with authentication

it('admin can delete', async () => {
  const { status } = await DELETE('/admin/Products(some-uuid)').as('alice')
  expect(status).to.equal(204)
})

it('viewer cannot delete', async () => {
  const { status } = await DELETE('/admin/Products(some-uuid)').as('carol')
  expect(status).to.equal(403)
})

Mocking external services

// Vitest spyOn
const S4 = await cds.connect.to('S4')
vi.spyOn(S4, 'run').mockResolvedValue([{ BusinessPartner: 'BP001' }])

Testing custom actions

it('submitOrder returns success', async () => {
  const { data, status } = await POST('/orders/submitOrder', {
    orderID: 'some-uuid'
  }).as('alice')
  expect(status).to.equal(200)
  expect(data.success).to.equal(true)
})

CSV test data

Put test data in db/data/. CAP loads these automatically in SQLite mode. For test isolation, use in-memory SQLite:

{
  "cds": {
    "requires": {
      "db": { "kind": "sqlite", "credentials": { "database": ":memory:" } }
    }
  }
}

Still on Jest? Known limitations

  • cds.test.expect is only a partial Chai emulation in Jest — not all Chai APIs work
  • Use jest.spyOn instead of vi.spyOn
  • Add --forceExit: "test": "jest --forceExit"
  • Set testTimeout: 30000 in jest.config.js
  • Plan migration to Vitest — CAP recommends migrating to Vitest, or using Jest's own expect if you need to stick with Jest

Common mistakes to avoid

  • ❌ Starting new CAP projects with Jest — Chai ESM issues mean incomplete assertion support

  • ✅ Use Vitest for all new projects; @cap-js/cds-test v1.0 is the stable recommended choice

  • ❌ Not setting testTimeout — default 5s too short for CAP server startup

  • ✅ Set testTimeout: 30000 in vitest.config.js

  • ❌ Testing with a shared HANA instance

  • ✅ Use SQLite :memory: for all unit and integration tests

  • ❌ Forgetting .as('user') on protected endpoints — silent 401 failures

  • ✅ Always specify the mock user matching the required role

  • ❌ Mocking cds.db directly

  • ✅ Use vi.spyOn(srv, 'run') on the connected service instance