[Mongoose][timekeeper] TypeError: Undefined type `FakeDate` at `fieldName`
- 2016 12/9
- カテゴリー : 未分類
- Mongoose . timekeeper
- コメントを書く
Node.js + Mongoose な構成のウェブサービスのテストコードで timekeeper という時間操作モジュールを利用していて FakeDate でハマったことをご紹介します。
timekeeper.freeze と new mongoose.Schema でエラーの事例
timekeeper.freeze と new mongoose.Schema でエラーが発生するテストコード
'use strict'; const mongoose = require("mongoose"); const timekeeper = require("timekeeper"); describe("FakeDate error", () => { timekeeper.freeze(new Date()); let schema = new mongoose.Schema({ createdAt: { type: Date } }); timekeeper.reset(); }); |
エラーメッセージ TypeError: Undefined type `FakeDate`
$ mocha test.js /Users/username/works/myapp/node_modules/mongoose/lib/schema.js:483 throw new TypeError('Undefined type `' + name + '` at `' + path + ^ TypeError: Undefined type `FakeDate` at `createdAt` Did you try nesting Schemas? You can only nest using refs or arrays. at Function.Schema.interpretAsType (/Users/username/works/myapp/node_modules/mongoose/lib/schema.js:483:11) at Schema.path (/Users/username/works/myapp/node_modules/mongoose/lib/schema.js:415:29) at Schema.add (/Users/username/works/myapp/node_modules/mongoose/lib/schema.js:310:12) at new Schema (/Users/username/works/myapp/node_modules/mongoose/lib/schema.js:88:10) at Suite.<anonymous> (/Users/username/works/myapp/test.js:8:16) at context.describe.context.context (/Users/username/works/myapp/node_modules/mocha/lib/interfaces/bdd.js:73:10) at Object.<anonymous> (/Users/username/works/myapp/test.js:6:1) at Module._compile (module.js:409:26) at Object.Module._extensions..js (module.js:416:10) at Module.load (/Users/username/works/myapp/node_modules/coffee-script/lib/coffee-script/coffee-script.js:211:36) at Function.Module._load (module.js:300:12) at Module.require (module.js:353:17) at require (internal/module.js:12:17) at /Users/username/works/myapp/node_modules/mocha/lib/mocha.js:157:27 at Array.forEach (native) at Mocha.loadFiles (/Users/username/works/myapp/node_modules/mocha/lib/mocha.js:154:14) at Mocha.run (/Users/username/works/myapp/node_modules/mocha/lib/mocha.js:326:31) at Object.<anonymous> (/Users/username/works/myapp/node_modules/mocha/bin/_mocha:350:7) at Module._compile (module.js:409:26) at Object.Module._extensions..js (module.js:416:10) at Module.load (module.js:343:32) at Function.Module._load (module.js:300:12) at Function.Module.runMain (module.js:441:10) at startup (node.js:139:18) at node.js:974:3 |
FakeDate は timekeeper が用意した Date
timekeeper が以下のように JavaScript の Date オブジェクトと、timekeeper で独自定義した FakeDate オブジェクトを入れ替える処理をしています。
/** * Replace the `Date` with `FakeDate`. */ function useFakeDate() { Date = FakeDate } /** * Restore the `Date` to `NativeDate`. */ function useNativeDate() { Date = NativeDate }
Date が Date でなく FakeDate に入れ替わってるタイミングで、new mongoose.Schema を呼び出すが FakeDate は MongooseTypes に定義されていない SchemaType なので例外が投げられてるっていう感じです。ザックリ説明すると。
new mongoose.Schema で SchemaType チェックしている Mongoose のコードはこの辺です lib/schema.js#L652-L671
テストコードの書き方次第でエラーは避けられる
timekeeper.freeze して timekeeper.reset するまでの間に、明示的に new mongoose.Schema したいテストコードを書くことはほぼないと思ってます。なので、new mongoose.Schema の処理を書いてる Model を定義してる module などは事前に require() しておくことでエラーを退避したいですね。