This content originally appeared on DEV Community 👩‍💻👨‍💻 and was authored by Julien Ripouteau
Have you ever written tests, in which the first 15-20 lines of each test are dedicated to just setting up the database state by using multiple models?
That's the problem Factorify is trying to solve
If you have already worked with Adonis.js, or Laravel, the concept of model factory must be very familiar to you. The idea here is exactly the same, Factorify is totally inspired by that.
I built Factorify because I quickly realized that Model Factories was a tool that I was really missing to do my tests while I was working on a different stack ( The current stack I have to work on is Hasura / AWS Lambda ).
Most of the time using Factorify is relevant when you are working on a stack without ORM, or if your ORM does not offer an equivalent feature. But any good ORM must offer a more or less similar system :
For example MikroORM, which is the ORM for the cool kids right now, offers factories: https://mikro-orm.io/docs/seeding#entity-factories
Prisma ORM doesn't seem to have a builtin solution, but there are third party plugins for : https://github.com/echobind/prisma-factory
Lucid, which is the ORM of Adonis.js, also have model factories : https://docs.adonisjs.com/guides/models/factories
etc.
Factorify is very, very simple to use. I will skip the database configuration step for keeping the post short, but you can find more information on the documentation website : https://factorify.julr.dev/
The first step is to simply define factors for each of your models. Here we will work on a database that has three models, users, and posts, and comments.
A user can have several posts, and a post can have several comments.
We start by defining the factories, with the relationships they have between them:
export const CommentFactory = defineFactory('comment', ({ faker }) => ({
content: faker.lorem.paragraph(),
}))
.build()
export const PostFactory = defineFactory<>('post', ({ faker }) => ({
title: faker.lorem.sentence(),
}))
// 👇 We define a relationship between the post and the comment model
.hasMany('comments', () => CommentFactory)
.build()
export const UserFactory = defineFactory<any>('user', ({ faker }) => ({
id: faker.datatype.number(),
name: faker.name.fullName(),
role: 'user'
}))
.state('admin', () => ({ role: 'admin' }))
// 👇 We define a relationship between the user and the post model
.hasMany('posts', () => PostFactory)
.build()
And that's it! We are ready to write tests that are clean.
In any of our tests, we can now use the factories to create the database state we need.
import { UserFactory } from '../factories.js'
test('My test ', () => {
// 👇 We create 3 users, each with 2 posts, and each post with 3 comments
const user = await UserFactory
.with('posts', 2, posts => posts.with('comments', 3))
.createMany(3)
// 👇 We can also create a single admin user by applying the previously defined state
const admin = await UserFactory.apply('admin')
.with('posts', 4)
.create()
// Now you can focus on testing your business logic, without having to write
// 15 lines of code to create the database state you need 🎉
})
And there you go. This makes test writing much easier and cleaner !
Factorify hides a lot of other nice features, like :
- Stubbing, which allows you not to persist anything in the database and just return the model to memory. Useful for testing an API : you just generate the model and store it in a variable, you send it to your API with supertest or whatever :
test('Should insert user', () => {
// 👇 Calling `make` or `makeMany` will generate the model in memory, without persisting it in the database
const user = await UserFactory.make()
request(app).post('/users').send(user).expect(200)
})
- Attributes overriding, which allows you to override the attributes of a model, without having to redefine the whole factory :
// 👇 We override the name attribute of the user
const user = await UserFactory.merge({ name: 'Julien' }).create()
And some other features that you can find on the documentation website : https://factorify.julr.dev/
I hope you will find Factorify useful, and if you have any feedback, please let me know ! I am also open to any PRs, if you want to contribute to the project.
You can find the project here on GitHub : https://github.com/julien-r44/factorify/
Please show some đź’– and star the project if you like it, it will help me a lot to get more visibility on the project.
This content originally appeared on DEV Community 👩‍💻👨‍💻 and was authored by Julien Ripouteau
Julien Ripouteau | Sciencx (2022-09-25T17:20:43+00:00) Introducing Factorify – A model factory library for Node.js. Retrieved from https://www.scien.cx/2022/09/25/introducing-factorify-a-model-factory-library-for-node-js/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.