Skip to main content

kickjs-write-controller-test

Use when adding a Vitest test that exercises an HTTP route or DI graph.

소스 정보

저장소
forinda/sdeploy
최근 소스 활동
2026년 9월 22일 19:55
감지된 SKILL.md 언어
영어
스타
0
포크
0

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
kickjs-write-controller-test
description
Use when adding a Vitest test that exercises an HTTP route or DI graph.
<!-- Generated by `kick g agents` for sdeploy. Edits are overwritten on the next refresh; keep customisation in a SKILL.local.md alongside. --> **Template** (copy/paste, adjust): ```ts import { describe, it, expect, beforeEach } from 'vitest' import request from 'supertest' import { Container } from '@forinda/kickjs' import { createTestApp } from '@forinda/kickjs-testing' // Side-effect import — registers the env schema, exactly as src/index.ts does. // `createTestApp` never loads the entry file, so without this // `ConfigService.get('YOUR_KEY')` is undefined under test while `@Value()` // still appears to work via its process.env fallback — the two disagree only // in tests. import '@/config' describe('UserController', () => { beforeEach(() => Container.reset()) // isolate DI between tests it('returns users', async () => { // `createTestApp` takes an OPTIONS OBJECT and returns // `{ app, container }`. Passing a bare array throws // "this.options.modules is not iterable"; the result has no `.get()`. // // Drive `app.handle` rather than `expressApp`: it is the Application's // own Node listener, so the test runs on whichever runtime the app is // configured with. Pass `runtime` to `createTestApp` to match production. const { app } = await createTestApp({ // Matches this project's `modules.style`. modules: [UserModule()], }) const res = await request(app.handle.bind(app)).get('/api/v1/users') expect(res.status).toBe(200) }) }) ``` **Typed handler signature** — pair with `kick typegen` so `ctx.body` / `params` / `query` are typed by the route's Zod schema: ```ts @Post('/', { body: createTodoSchema }) async create(ctx: Ctx<KickRoutes.TodoController['create']>) { // ctx.body is typed from createTodoSchema; ctx.params from the route. // Returning (vs ctx.created) lets typegen infer the response type. return reply(201, await this.service.create(ctx.body)) } ``` **Red flags**: - `new Container()` — wrong; use `Container.reset()` in `beforeEach` or `Container.create()` for fully isolated graphs. - `Container.getInstance().reset()` — wrong; same fix. - Sharing a container instance across `it()` blocks — leaks registrations between tests. - Injecting a `Scope.REQUEST` service into a `SINGLETON` — container throws at resolve. Singletons must resolve request-scoped services explicitly per call. - Calling `getRequestValue<string>('traceId')` — the generic slot is the **key** type, not the value type; widens key and bypasses typed lookup. - Asserting on `res.body.requestId` when `requestId()` middleware isn't mounted in the test app — value will be `undefined`. - Using `Scope.REQUEST` services in a test without mounting `requestScopeMiddleware()` — `getRequestValue` silently returns `undefined`; `getRequestStore` throws. **Nuances**: - `@Inject` and `@Autowired` are interchangeable — same runtime, same types; pick by readability. - `@Value('MISSING_KEY')` with no default **throws on property access**, not at construction — tests that exercise the getter will surface the missing-env issue.
GitHub에서 보기