Automatic fixtures for TypeORM. Speed up creating the database entities you need for your tests.
The fixture object will automatically create and keep track of every entity required to construct the target one. It has an internal context and reuses the last created entity of a given type every time it is required to create a new object.
Requires TypeORM >= 0.3.0.
npm install typeorm-autofixtures- it only creates non-nullable properties and relations
- for relations
- One-to-One: create only if not owner*
- Many-to-One: always create
- One-to-Many: never create
- Many-to-Many: never create
*Owner: the side of the relation with a join column (Many-to-Many or One-to-One).
import { Fixture } from 'typeorm-autofixtures';
beforeEach(async () => {
const dataSource = await getDataSource();
repository = dataSource.createEntityManager();
fixture = new Fixture(dataSource);
});
it('Creates a Task', async () => {
const task = await fixture.create(Task);
expect(task.id).toBeDefined();
expect(task.project).toBeDefined();
expect(task.users).toBeUndefined();
});Fixture will:
- Create the object Task and stub all of its non-nullable properties.
- Loop through all its properties and relations:
- Find MANY-TO-ONE for Task.project -> Project.tasks: Create a Project
- Loop through all Project properties and relations:
- Find ONE-TO-MANY for Project.tasks -> Task.project: No Action (one-to-many)
- Find MANY-TO-MANY for Task.users -> User.tasks: No Action (many-to-many)
- Returns the Task object populated.
Every time an object is created, it stays in the context. So, calling methods like this:
const task1 = await fixture.create(Task);
const task2 = await fixture.create(Task);
expect(task1.project).toBe(task2.project);Will automatically reuse the previously created Project for both Tasks.
If you don't want this behaviour, just call fixture.resetContext() and your next calls will be in a completely different object graph.
const task1 = await fixture.create(Task);
fixture.resetContext();
const task2 = await fixture.create(Task);
expect(task1.project).not.toBe(task2.project);Every fixture.create(Type) accepts a Partial<Type> as a parameter where you can specify your own values for the creation of the object.
Ex: Scalar types:
const project = await fixture.create(Project, { name: 'My Project' });
expect(project.name).toBe('My Project');Or objects:
const project = await fixture.create(Project);
const task = await fixture.create(Task, { project });
expect(task.project).toBe(project);Use createMany to create multiple entities at once:
const tasks = await fixture.createMany(5, Task);
expect(tasks).toHaveLength(5);It also accepts optional values applied to every created entity:
const tasks = await fixture.createMany(3, Task, { name: 'Bulk Task' });When creating an entity, non-nullable columns are automatically populated with default values based on their type:
| Column type | Default value |
|---|---|
int, integer, bigint, smallint, decimal, numeric, float, double, real |
0 |
bool, boolean |
false |
date, time, timestamp, datetime |
new Date(0) (epoch) |
json, jsonb |
{} |
enum |
First enum value |
uuid |
Skipped (auto-generated by the database) |
String types (varchar, text, etc.) |
Generated value (see below) |
String columns get automatically generated values that respect column length constraints (defaulting to 255 if unspecified).
- Unique columns get a random UUID suffix for guaranteed uniqueness:
name1-a3f2b1c0 - Non-unique string columns get a counter-based suffix:
name1-1
The prefix is built from {columnName}{index} and is trimmed as needed so the value always fits within the column's max length.
Enable debug logging to see what Fixture is creating:
Fixture.IsLogEnabled = true;This is a static property (default false). When enabled, creation progress and entity relationships are logged to the console.
You can find many more examples in the fixture's test file.