Skip to content

faboulaws/fakingoose

Repository files navigation

fakingoose

Build Status Coverage Status

An automatic mock data generator for mongoose using schema definition.

Install

npm install fakingoose

Usage

const {
    factory
} = require('fakingoose');
const entityFactory = factory(model, options);

factory(model, options)

  • model <Schema> or <Model>: Mongoose model or schema.
  • options <? Object>: Generation options are optional. The factory would generate data for all fields based on the schema alone. For cases where there is a need for custom values, options can be used to define custom values or data generation setting per field.
    • options.<propertyName>.value <mixed>: A static value for each generated mock object.
    • options.<propertyName>.value: <function> a function for generating a dynamic value per item. This function receives the mock object as first argument.
    • options.<propertyName>.skip <boolean>: When set to true would skip the field.
    • options.<propertyName>.type <string>: The sub-type for this field type. For example <String> schema type supports email , firsname and lastname .
    • options.\<propertyName\>.populateWithSchema: Uses a schema to generate mocks of related models
    • options.\<propertyName\>.populateWithFactory: Uses another factory to generate mocks of related models. This options provides more flexibility than populateWithSchema, taking advantage of custom behaviours of factory via Factory options.
    • options.\<propertyName\>.size <int>: (Array values only) When specified, will ensure that said array field has given number of elements. By default, this is set to 2.

Usage example

const mongoose = require('mongoose');
const {
    factory
} = require('fakingoose');
const {
    Schema
} = mongoose;

const authorSchema = new Schema({
    id: Schema.Types.ObjectId,
    title: {
        type: String,
        enum: ['Mr', 'Mrs', 'Dr']
    },
    fullname: String,
    username: String,
    email: String,
    favoriteQuote: String,
});

const blogSchema = new Schema({
    title: String,
    author: authorSchema,
    body: String,
    comments: [{
        body: String,
        date: Date
    }],
    date: {
        type: Date,
        default: Date.now
    },
    hidden: Boolean,
    meta: {
        votes: {
            type: Number,
            min: 0
        },
        favs: {
            type: Number,
            min: 0
        }
    }
});

const options = {
    author: {
        email: {
            type: 'email',
        },
        username: {
            value: (object) => {
                return object.fullname.toLowerCase().replace(/\s/g, '.');
            }
        },
        favoriteQuote: {
            skip: true
        }
    },
};
const blogFactory = factory(blogSchema, options);

const mock = blogFactory.generate({
    author: {
        fullname: 'John Doe'
    }
});

sample output

{
  "title":"8tnkcjplr",
  "author":{
    "id":"5d513f762a48134adb1868d7",
    "title":"Dr",
    "fullname":"John Doe",
    "username":"john.doe",
    "email":"re@sisuki.mc",
    "_id":"5d513f762a48134adb1868d8"
  },
  "body":"ebjwad6*keskl",
  "comments":[
    {
      "body":"d$*t9y3",
      "date":"2019-08-12T10:29:10.193Z",
      "_id":"5d513f762a48134adb1868d9"
    },
    {
      "body":"jv5o[",
      "date":"2019-08-12T10:29:10.193Z",
      "_id":"5d513f762a48134adb1868da"
    }
  ],
  "hidden":false,
  "meta":{"votes":-3419053502758912,"favs":3323094479405056},
  "_id":"5d513f762a48134adb1868db"
}

Define options for nested properties

To define options for nested a property use the nested property path (property names sperated by a dot). Example:

const options = {
    "meta.votes": {
        value: 0
    }, // set value for 'votes' property under meta
    "meta.favs": {
        skip: true
    } // skip value for 'favs' property under meta
}

Skipping multiple nested properties

Multiple nested properties can be skipped from parent property. Example:

const accountSchema = new mongoose.Schema({
    user: {
        generalInfo: {
            firstName: String,
            lastName: String,
            age: Number
        },
        address: {
            postCode: String,
            street: String
        }
    }
});
const accountFactory = factory(accountSchema, options);

To generate mocks without an address define options as below you have to override the default factory's options:

const options = {
    'user.address': {
        skip: true
    }
}

or

const options = {
    user: {
        address: {
            skip: true
        }
    }
}

then

const mockObject = accountFactory.generate({}, options);

Generating ObjectId values

When generating ObjectId values, you can choose to Stringify the generated ObjectId by using the tostring option. By default this options is true , so all generated ObjectIds would be converted to a String. Set tostring to false to disable this behaviour.

Example: In the snippet below all ObjectIds generated are not stringified.

const friendSchema = new Schema({
    id: Schema.Types.ObjectId,
    friendIds: [{
        type: Schema.Types.ObjectId
    }],
    bestFriend: {
        id: Schema.Types.ObjectId
    }
});

const amigoFactory = factory(friendSchema, {
    id: {
        tostring: false
    },
    friendIds: {
        tostring: false
    },
    'bestFriend.id': {
        tostring: false
    }
});

Global settings

To disable stringification globally use factory.setGlobalObjectIdOptions .

Example:

const friendSchema = new Schema({
    id: Schema.Types.ObjectId,
    friendIds: [{
        type: Schema.Types.ObjectId
    }],
    bestFriend: {
        id: Schema.Types.ObjectId
    }
});

const amigoFactory = factory(friendSchema).setGlobalObjectIdOptions({
    tostring: false
});

Generating mocks for related models (Populate)

Mongoose provides an API for automatically replacing the specified paths in the document with document(s) from other collection(s). This package provides a similar functionality when generating mocks.

An example: In the snippet below we have two schemas, activitySchema & personSchema .

const activitySchema = new mongoose.Schema({
    name: String,
    value: String,
});

const personSchema = new mongoose.Schema({
    email: String,
    name: {
        type: String,
    },
    activities: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'activity'
    }],
});

When generating mock data from the personSchema we should get the sample below

{
    email: 'l7@eiwtef%(pzitx',
    name: 'ym](ht7ucas*',
    activities: ['60f1e810a8b8ac392c3869b7', '60f1e810a8b8ac392c3869b8'],
    _id: '60f1e810a8b8ac392c3869b9'
}

In some cases we might want to receive activity data instead of activity ID in the activities property, so we have a structure like below.

 {
     email: ')5b2[dj@@)p91(',
     name: 'qo[jk!',
     activities: [{
             name: '7^*8h^@!zp^!*hqwn',
             value: ']55f$hmva',
             _id: '60f1e51dead56f35c7ed4f62'
         },
         {
             name: 'r!cv!k!p#vqfqt4a9k',
             value: '$@6k!z&oflj6',
             _id: '60f1e51dead56f35c7ed4f63'
         }
     ],
     _id: '60f1e51dead56f35c7ed4f64'
 }

Let's look at two seperate ways we can achieve this:

  • options.\<propertyName\>.populateWithSchema: Uses a schema to generate mocks of related models.

  • options.\<propertyName\>.populateWithFactory: Uses another factory to generate mocks of related models. This options provides more flexibility than populateWithSchema, taking advantage of custom behaviors of factory via Factory options.

Example: options.populateWithFactory

  const activityFactory = mocker(activitySchema)

  const personFactory = mocker(personSchema, {
      activities: {
          populateWithFactory: activityFactory
      }
  })
  const mock = personFactory.generate()

Example: options.populateWithSchema

const myFactory = mocker(schema, {
    activities: {
        populateWithSchema: activitySchema
    }
})
const mock = myFactory.generate()

Generating decimal (Decimal128) values

When generating decimal values, you can choose to Stringify the generated number by using the tostring option. By default this options is true , so all generated numbers would be converted to a String. Set tostring to false to disable this behaviour.

Example: In the snippet below all numbers generated are not stringified.

const productSchema = new Schema({
    price: Schema.Types.Decimal128
});

const productFactory = factory(productSchema, {
    price: {
        tostring: false
    }
});

Generating a variable-sized array of items per field

When generating array values, you can specify a size parameter to ensure the array field has that many elements. By default, this is set to 2.

Example: Each new user will now have 10 new statuses to start.

const userSchema = new mongoose.Schema({
    email: String,
    name: {
        type: String,
    },
    activities: [{
        type: String,
    }],
});

const userFactory = factory(userSchema, {
    activities: {
        size: 10
    }
});

Global settings

To disable stringification globally use factory.setGlobalDecimal128Options .

Example:

const productSchema = new Schema({
    price: Schema.Types.Decimal128
});

const productFactory = factory(productSchema).setGlobalDecimal128Options({
    tostring: false
});

Override factory options per mock generated

I some cases we want to override options that we used to initialise a factory. These options can be overridden in the generate() method of the factory.

Example

const schema = new Schema({
    updated: {
        type: Date,
        default: Date.now
    },
    title: String,
    content: String,
});

const options = {
    updated: {
        skip: true
    }
};

const myFactory = mocker(schema, options);
const mockWithoutUpdated = myFactory.generate({}); // here use options used to initilize the factory. We skip the "updated: field

const mockWithoutTitle = myFactory.generate({}, { // here use custom options. We skip the "title: field
    title: {
        skip: true
    }
});

Supported Types

  • String
  • Array
  • Number
  • Decimal128
  • ObjectId
  • Boolean
  • Mixed
  • Buffer
  • Embedded
  • Date
  • Map

Mongoose version Support

Version Supported
7.x
6.x
5.x
4.x

About

An automatic mock data generator for mongoose using the schema definition

Resources

License

Stars

Watchers

Forks

Packages

No packages published