Question: how to unit test without hitting the DB
Problem
I'm trying to write some unit tests of code that uses typeorm without hitting the DB. I'm using `getRepository` in the code to do stuff. In my tests ideally I'd like to call `getRepository(SomeEntity)` and then use sinon to `sinon.mock(repository).expects('find').withArgs(...).returns(stuff)`. To avoid hitting the DB I thought I'd just not call `createConnection` if I'm in the unit tests context. However I ran into the problem that `getRepository` calls connection manager which looks if it has a connection initialized and if not throws. What would be the recommended way of handling this? Is it possible to create a "dummy" connection somehow which doesn't try to connect anywhere?
Unverified for your environment
Select your OS to check compatibility.
2 Fixes
Create a Mock Connection for TypeORM Unit Testing
The issue arises because TypeORM's `getRepository` function checks for an active database connection. If no connection exists, it throws an error. This behavior prevents unit tests from running without hitting the actual database.
Awaiting Verification
Be the first to verify this fix
- 1
Install Required Packages
Ensure you have the necessary packages for mocking and testing. You will need 'sinon' for mocking and 'typeorm' for your entity definitions.
bashnpm install --save-dev sinon typeorm - 2
Create a Mock Connection
Use TypeORM's `createConnection` method to create a mock connection that does not connect to a real database. This can be done by providing a connection options object with a 'synchronize' flag set to false.
typescriptimport { createConnection } from 'typeorm'; const mockConnection = await createConnection({ type: 'sqlite', database: ':memory:', entities: [SomeEntity], synchronize: false, logging: false }); - 3
Override getRepository with Mock
In your test setup, override the `getRepository` method to return a mocked repository. Use Sinon to create a mock repository that simulates the behavior of the actual repository without hitting the database.
typescriptimport { getRepository } from 'typeorm'; import sinon from 'sinon'; const repositoryMock = sinon.createStubInstance(SomeRepository); repositoryMock.find.returns(Promise.resolve(stuff)); sinon.stub(typeorm, 'getRepository').returns(repositoryMock); - 4
Run Your Tests
Execute your unit tests to ensure that they run without connecting to the database. Verify that the mocked repository methods are called as expected.
typescriptimport { expect } from 'chai'; describe('Your Test Suite', () => { it('should call find method', async () => { await yourFunction(); expect(repositoryMock.find.called).to.be.true; }); }); - 5
Clean Up Mocks
After your tests have run, restore the original `getRepository` method to avoid affecting other tests. This ensures that your testing environment remains clean.
typescriptafterEach(() => { sinon.restore(); });
Validation
Confirm the fix by running your unit tests and ensuring they pass without any database connection errors. Check that the mocked methods are called with the expected arguments.
Sign in to verify this fix
1 low-confidence fix
Implement Mock Repository for TypeORM Unit Testing
The issue arises because TypeORM's `getRepository` method checks for an active database connection. When running unit tests, if no connection is established, it throws an error. This is problematic for unit tests that should not interact with the database.
Awaiting Verification
Be the first to verify this fix
- 1
Create a Mock Connection
Set up a mock connection that simulates TypeORM's connection manager without actually connecting to a database. This allows you to call `getRepository` without encountering errors.
typescriptimport { createConnection, getConnection } from 'typeorm'; import { SomeEntity } from './entities/SomeEntity'; const mockConnection = async () => { await createConnection({ type: 'sqlite', database: ':memory:', entities: [SomeEntity], synchronize: true, logging: false, }); }; - 2
Use Sinon to Mock Repository Methods
In your unit tests, use Sinon to mock the repository methods you intend to test. This allows you to define expected behaviors without hitting the database.
typescriptimport sinon from 'sinon'; import { getRepository } from 'typeorm'; const repository = getRepository(SomeEntity); const mockFind = sinon.mock(repository); mockFind.expects('find').withArgs({ id: 1 }).returns(Promise.resolve([{ id: 1, name: 'Test' }])); - 3
Initialize Mock Connection in Test Setup
Ensure that the mock connection is initialized before running your tests. This can be done in a `before` hook in your test suite.
typescriptbefore(async () => { await mockConnection(); }); - 4
Run Your Tests
Execute your unit tests as usual. With the mock repository in place, you should be able to test your code without hitting the actual database.
typescriptdescribe('SomeEntity Tests', () => { it('should find an entity by ID', async () => { const result = await repository.find({ id: 1 }); expect(result).to.deep.equal([{ id: 1, name: 'Test' }]); }); });
Validation
Confirm that the tests run successfully without any database connection errors. Ensure that the mocked methods return the expected results as defined in your tests.
Sign in to verify this fix
Environment
Submitted by
Alex Chen
2450 rep