[Mongoose][timekeeper] TypeError: Undefined type `FakeDate` at `fieldName`

Tadashi Shigeoka ·  Fri, December 9, 2016

I’ll introduce how I got stuck with FakeDate while using timekeeper, a time manipulation module, in test code for a web service with Node.js + Mongoose configuration.

mongoose | マングース

Error example with timekeeper.freeze and new mongoose.Schema

Test code that causes errors with timekeeper.freeze and 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();
});

Error message 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. (/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. (/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. (/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 is a Date prepared by timekeeper

timekeeper processes swapping JavaScript’s Date object with timekeeper’s custom-defined FakeDate object as follows:

  /**
   * Replace the `Date` with `FakeDate`.
   */
  function useFakeDate() {
    Date = FakeDate
  }

/**

  • Restore the Date to NativeDate. */ function useNativeDate() { Date = NativeDate }

When Date is swapped with FakeDate instead of Date, calling new mongoose.Schema throws an exception because FakeDate is not a SchemaType defined in MongooseTypes. Roughly speaking.

The Mongoose code that checks SchemaType in new mongoose.Schema is around here: lib/schema.js#L652-L671

Errors can be avoided depending on how test code is written

I don’t think there are many cases where you explicitly write new mongoose.Schema in test code between timekeeper.freeze and timekeeper.reset. So, modules that define Models with new mongoose.Schema processing should be require()d beforehand to avoid errors.

That’s all from the Gemba.