factory-girl
factory-girl
is a factory library for Node.js and the browser that is inspired by Factory_girl. It works asynchronously and supports associations and the use of functions for generating attributes.
Installation
Node.js:
npm install factory-girl
To use factory-girl
in the browser or other JavaScript environments, there are
builds for numerous module systems in the dist/
directory.
Usage
Refer to the tutorial for a gentle introduction of building a simple
user factory.
Here's the crash course:
var factory = require('factory-girl');
var User = require('../models/user');
factory.define('user', User, {
username: 'Bob',
score: 50,
});
factory.build('user').then(user => {
console.log(user);
});
Defining Factories
Define factories using the factory.define()
method.
For example:
factory.define('product', Product, {
id: factory.sequence('Product.id', (n) => `product_${n}`),
launchDate: () => new Date(),
asyncData: () => fetch('some/resource'),
});
factory.define('user', User, {
email: factory.seq('User.email', (n) => `user${n}@ymail.com`),
about: factory.chance('sentence'),
profileImage: factory.assoc('profile_image', '_id'),
addresses: factory.assocMany('address', 2, '_id'),
creditCardNumber: factory.assocAttrs('credit_card', 'number', {type: 'masterCard'}),
twitterDetails: factory.assocAttrs('twitter_details'),
});
factory.define('account', Account, buildOptions => {
var attrs = {
confirmed: false,
confirmedAt: null
};
if (buildOptions.confirmedUser) {
attrs.confirmed = true;
attrs.confirmedAt = new Date();
}
return attrs;
});
factory.build('account', {}, {confirmed: true});
Options
Options can be provided when you define a factory:
factory.define('user', User, { foo: 'bar' }, options);
Alternatively you can set options for the factory that will get applied for all model-factories:
factory.withOptions(options);
Currently the supported options are:
afterBuild: function(model, attrs, buildOptions)
Provides a function that is called after the model is built.
The function should return the instance or throw an error. For asynchronous functions, it should return a promise that either resolves with the instance or rejects with the error.
afterCreate: function(model, attrs, buildOptions)
Provides a function that is called after a new model instance is saved. The function
should return the instance or throw an error. For asynchronous functions, it should return
a promise that resolves with the instance or rejects with the error.
factory.define('user', User, {foo: 'bar'}, {
afterBuild: (model, attrs, buildOptions) => {
return doSomethingAsync(model).then(() => {
doWhateverElse(model);
return model;
});
},
afterCreate: (model, attrs, buildOptions) => {
modify(model);
if ('something' === 'wrong') {
throw new Error;
}
maybeLog('something');
return model;
}
});
Using Factories
Factory#attrs
Generates and returns model attributes as an object hash instead of the model instance.
This may be useful where you need a JSON representation of the model e.g. mocking an API
response.
factory.attrs('post').then(postAttrs => {
});
factory.attrs('post', {title: 'Foo', content: 'Bar'}).then(postAttrs => {
});
factory.attrs('post', {title: 'Foo'}, {hasComments: true}).then(postAttrs => {
});
You can use Factory#attrsMany
to generate a set of model attributes
factory.attrsMany('post', 5, [{title: 'foo1'}, {title: 'foo2'}]).then(postAttrsArray => {
debug(postAttrsArray);
});
Refer API docs for complete API documentation.
Factory#build
Builds a new model instance that is not persisted.
factory.build('post').then(post => {
});
The buildMany
version builds an array of model instances.
factory.buildMany('post', 5).then(postsArray => {
});
Similar to Factory#attrs
, you can pass attributes to override or buildOptions.
Factory#create(name, attrs, buildOptions)
Builds a new model instance that is persisted.
factory.create('post').then(post => {
});
The createMany version creates an array of model instances.
factory.createMany('post', 5).then(postsArray => {
});
Similar to Factory#attrs
and Factory#build
, you can pass attrs
to override and
buildOptions
.
Factory#cleanup
Destroys all of the created models. This is done using the adapter's destroy
method.
It might be useful to clear all created models before each test or testSuite.
Adapters
Adapters provide support for different databases and ORMs. Adapters can be registered for
specific models, or as the 'default adapter', which is used for any models for which an
adapter has not been specified. See the adapter docs for usage, but typical usage is:
const adapter = new factory.MongooseAdapter();
factory.setAdapter(adapter);
factory.setAdapter(adapter, 'factory-name');
Creating new Factories
You can create multiple factories which have different settings:
var anotherFactory = new factory.FactoryGirl();
anotherFactory.setAdapter(new MongooseAdapter());
History
This module started out as a fork of
factory-lady, but the fork deviated quite a
bit. This module uses an adapter to talk to your models so it can support different ORMs
such as Bookshelf,
Sequelize,
JugglingDB, and
Mongoose (and doesn't use throw
for errors that might occur during save).
Version 4.0 is a complete rewrite with thanks to @chetanism.
License
Copyright (c) 2016 Chetan Verma.
Copyright (c) 2014 Simon Wade.
Copyright (c) 2011 Peter Jihoon Kim.
This software is licensed under the MIT
License.