はじめに
express.jsのコントローラー層のテストやTypeORMエンティティ(モデル)のテストを書く際、
毎回DBデータの作成に結構時間を取られたりしますが、Factoryメソッドを準備すれば
サクサクデータを作成してテストに集中することが出来ます。
注意
MySQLやPostgresqlのよなリレーショナルデータベース用の記事です。
MongoDB等には対応していません。
やりかた
自分でファクトリーの仕組みを作ってもいいのですが、typeorm-factoryという
便利なライブラリがあるため今回はそっちに全乗っかりします。
RailsのFactoryGirlFactoryBotのようなものです。
インストール
npm install --save-dev typeorm-factory
Factoryの作成
テストディレクトリ以下にhelperなり適当なディレクトリを作り、ファクトリーを作っていきます。
モデルが増えてきたら1モデル1ファイルに分割する等、お好みで管理していけばいいと思いますが
ここでは全モデル分1ファイルで定義します。
例として、Comment, Author, Postというエンティティを持っている場合
import { Factory } from 'typeorm-factory'
// エンティティ(モデル)のComment, Author, Postもインポートしておく
// .attr → 普通のカラムはこれで作ります
// .secuence → ユニーク成約等があるカラムの場合はindexを受取る無名関数を使って一意化出来ます
export const CommentFactory = new Factory(Comment)
.sequence("text", (i) => `text ${i}`)
.attr("authorName", "John Doe");
export const AuthorFactory = new Factory(Author)
.sequence("firstName", (i) => `John ${i}`)
.sequence("lastName", (i) => `Doe ${i}`);
// .assocMany → toManyリレーション作成。最後の引数で一気に作る数を指定出来ます
// .assocOne → toOneリレーションを作成
export const PostFactory = new Factory(Post)
.sequence("title", (i) => `title ${i}`)
.sequence("text", (i) => `text ${i}`)
.attr("likesCount", 10)
.assocMany("comments", CommentFactory, 2)
.assocOne("author", AuthorFactory);
使う
create()
メソッドを使うとDBにもデータ作成、build()
メソッドを使うとインスタンスのみ作成されます。
また、どちらのメソッドも好きなデータで上書きして作成することも出来ます。
一度に沢山作りたければcreateList()
buildList()
というものもあります。
コードには書いてませんが、DBコネクションがないとエラーになるため事前にコネクションを張って下さい。
jestならbeforeEachかbeforeAllで張ってafterEachかafterAllで閉じる感じでしょうか。
import { AuthorFactory, CommentFactory } from '../../helpers/factory'
describe('Post', () => {
describe('someMethod', () => {
it('なんたらかんたら', async () => {
// DB作成
const author1 = await AuthorFactory.create({firstName: "こうやって上書きできます"})
// インスタンスのみ作成
const author2 = await AuthorFactory.build()
// リレーションも上書きできます。この場合はauthor1を親に持ったpostが作られます
const post= await PostFactory.create({ author: author1 })
// 一気に作る場合
const posts= await PostFactory.createList({ author: author1 }, 10)
// なんやかんやテストする
// post.someMethod()
// expect().toBe()
})
})
})