Hello Everyone!
So, today I'll show you how to configure your code to make tests with TypeORM and Jest.
Modules
First thing first, let's install some modules in our node environment. I'm using yarn:
yarn add jest ts-jest @types/jest -D
yarn add typeorm typescript pg
Then, let's create our tsconfig file:
yarn tsc --init
Jest configs
Ok, now we need to configure our jest.config.js and there are my conigs:
module.exports = {
clearMocks: true,
maxWorkers: 1,
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: [
'**/__tests__/**/*.[jt]s?(x)',
'!**/__tests__/coverage/**',
'!**/__tests__/utils/**',
'!**/__tests__/images/**',
],
};
I like to make a directory named tests in the root of the project to make tests.
TypeORM configs
And I like to create a ormconfig.js. Be comfortable to make a .json or .env.
module.exports = {
name: 'default',
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: 'postgres',
database: 'tests',
dropSchema: true,
logging: false,
synchroize: true,
migrationsRun: true,
entities: ['src/database/entities/*.ts'],
migrations: ['src/database/migrations/*.ts'],
cli: {
entitiesDir: 'src/database/entities',
migrationsDir: 'src/database/migrations',
},
};
So, let the dropSchema: true
because this will delete your data after the tests.
I like to let migrationsRun: true
to automatically run migrations before the tests.
I'm using postgres, but be comfortable to use your favorite database.
Creating connection file
Let's create a connection.ts to export some functions to run in our tests.
import {createConnection, getConnection} from 'typeorm';
const connection = {
async create(){
await createConnection();
},
async close(){
await getConnection().close();
},
async clear(){
const connection = getConnection();
const entities = connection.entityMetadatas;
entities.forEach(async (entity) => {
const repository = connection.getRepository(entity.name);
await repository.query(`DELETE FROM ${entity.tableName}`);
});
},
};
export default connection;
The clear method will delete all data for every single entity registered in our connection.
Creating a test
So, in your tests, just put this code:
import connection from '../src/connection';
beforeAll(async ()=>{
await connection.create();
});
afterAll(async ()=>{
await connection.close();
});
beforeEach(async () => {
await connection.clear();
});
it('creates a user', () => {
// TODO
})
And that's it :)
Github project
If you want to see the full project just click here
Top comments (15)
Hello dude!
First of all, thank you by the great article, it help me a lot.
I've noticed that in the
clear
function you put anawait
function inside aforEach
iterator, but in this case the promise will not work properly.I solve this issue using the
map
instead theforEach
and placing the map result inside aPromise.all()
. This works great to me.Can you put your example here please?
Here you go:
I'm currently using typeorm 0.2.31 and they allow for
repo.clear()
to truncate / drop the tableI ended up putting a separate call to
testConn.create()
in a module called my Jest Global setup hook so I could instruct Jest to refresh the database at the start of the test run by dropping the schema and recreating it from migrations by passing indropSchema: true
Example:
Then, if using TypeScript, add
globalSetup
andglobalTeardown
to yourjest.config.js
file like so (at bottom):Then, in globalSetup.js you can call your TypeScript setup module by doing the following:
The MyTestLifecycle module (in Typescript) just calls
testConn.create(true)
so that the schema is dropped at the start of all my tests and then re-created by running the migrations:Let me know when this is useful you!
I do not want to use a real database connection in the tests, how to test my custom Repository.
stackoverflow.com/questions/675802...
This will be a problem when you set the relations between tables.
You can do the following way:
The TypeORM also has the
synchronize
method, so you can simplify this code:true
means that TypeORM will drop all tables before syncing.You can just drop the schema and recreate it from migrations. See my other response.
Valeu mano, vc me ajudou muito agora.
This is a wrong practice. unit tests should not use external resources like databases. In the other hand integration tests use api calls and check the whole functionality of the api. but whet you implemented here is somewhat in between that
Man, that's beautiful.
Just a thing about the connection.clear inside beforeEach(), maybe it's better put it inside afterEach() and then another clear() inside afterAll().
Thank You!
You can use global setup and teardown files that can run the create and clear functions without repeating them in each file
jestjs.io/docs/en/configuration#gl...
OMG, you saved my life!! Thx! Congrats by the awesome article
Thank you for this article.
I guess it's necessary to use "--runInBand" flag when running tests with this setting. Otherwise, DB connection may be closed before executing all test files