13
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

TypeORMのテストでFactoryを使って楽をする

Last updated at Posted at 2019-02-16

はじめに

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というエンティティを持っている場合

factory.ts

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()
    })
  })
})
13
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?