はじめに
本記事は「NestJs」での実装を行いながら、「Swagger」でAPI仕様書を作成し、仕様書を元に「Dredd」で自動テストを行うといった作業を行なっていた時にハマったことについて説明します。
ざっくり2つあります。
- Optionalなプロパティ
- Unionなプロパティ
環境
- Docker
- NestJs
- Swagger
- Dredd
Optionalなプロパティの定義
NG例
export class User {
@IsNumber()
@ApiProperty({ type: Number, example: 1 })
id: number;
@IsString()
@ApiProperty({ type: String, example: 'hoge huga' })
name: string;
@IsNumber()
@IsOptional()
@ApiPropertyOptional({ type: Number, example: 2, required: false})
@Transform(({ value }) => parseInt(value))
partnerUserId?: number;
}
partnerUserIdはNullの場合があるため、Optionalとなっています。
上記定義では、Dreddでのテストにて「number型」に「object」型を格納しているとエラーが発生します。
原因とOK例
原因は@ApiPropatyOptional内での定義漏れです。
nulltable:trueが必要でした。
export class User {
@IsNumber()
@ApiProperty({ type: Number, example: 1 })
id: number;
@IsString()
@ApiProperty({ type: String, example: 'hoge huga' })
name: string;
@IsNumber()
@IsOptional()
@ApiPropertyOptional({ type: Number, example: 2, required: false, nullable: true })
@Transform(({ value }) => parseInt(value))
partnerUserId?: number;
}
unionなプロパティ
NG例
class expression {
@ApiProperty({ example: 'operator' })
type: string;
@ApiProperty({
type: String || Number
example: {
number: 350,
string: 'totalAmount',
},
required: false,
})
value: number | string;
}
計算式を格納するようなクラスです。
TypeがOperatorの時は四則演算子を、numの時は数値を格納するイメージです。
こちらはDreddでのテストにて「number」型に「string」型を格納したとエラーが発生します。
原因とOK例
どうやらNestJsで使用できるSwaggerアノテーションはunionに対応していないようです。
以下のように修正します。
class expression {
@ApiProperty({ example: 'operator' })
type: string;
@ApiProperty({
example: 350,
required: false,
})
value?: number;
@ApiProperty({ example: 'multiply', required: false })
operator?: string;
}
Optionalでvalueかoperatorのどちらかを使用できるようにしました。
正直あまりいけてないのですが、APIの型定義のみで使用するClassなので妥協しました。
終わり
解決にすこし苦労したので記事にしました。
自動テストを通すために、実処理で使用する型を変更するのは本末転倒なので避けた方がいいなぁと思いながら作業しました。