Skip to content

Instantly share code, notes, and snippets.

@joseym
Created January 21, 2019 20:54
Show Gist options
  • Save joseym/6849bf7fe09db3ecaba0eaded61d3755 to your computer and use it in GitHub Desktop.
Save joseym/6849bf7fe09db3ecaba0eaded61d3755 to your computer and use it in GitHub Desktop.
TypeORM DB Connection Stubs
import * as typeorm from 'typeorm';
import { AlreadyHasActiveConnectionError } from 'typeorm/error/AlreadyHasActiveConnectionError';
import { Driver } from 'typeorm/driver/Driver';
import { DriverFactory } from 'typeorm/driver/DriverFactory';
import { PostgresDriver } from 'typeorm/driver/postgres/PostgresDriver';
import { stub } from 'sinon';
// Load all of my entities from the index
import * as entities from './../../src/entity'
// I'm using postgres, so I just force the PG driver, but dont connect
class myFakeDBDriver extends PostgresDriver {
async connect(): Promise<void> {}
}
// again, just overwriting the driver factory method to connect to fake PG
class myDriverFactory extends DriverFactory {
create(connection: Connection): Driver {
return new myFakeDBDriver(connection);
}
}
// Overwriting the connection driver with an accessor to ensure we're using the fake driver.
// Its readonly property value wouldn't allow me to reset this from a child constructor.
class Connection extends typeorm.Connection {
_driver: typeorm.Driver;
get driver(): typeorm.Driver {
return this._driver;
}
set driver(options) {
this._driver = new myDriverFactory().create(this);
}
}
export class ConnectionManager extends typeorm.ConnectionManager {
// Complete copy from ConnectionManager.connect, but now the Connection class uses the fake driver.
create(options: typeorm.ConnectionOptions): Connection {
// check if such connection is already registered
const existConnection = this.connections.find(connection => connection.name === (options.name || "default"));
if (existConnection) {
// if connection is registered and its not closed then throw an error
if (existConnection.isConnected)
throw new AlreadyHasActiveConnectionError(options.name || "default");
// if its registered but closed then simply remove it from the manager
this.connections.splice(this.connections.indexOf(existConnection), 1);
}
// create a new connection
const connection = new Connection(options);
this.connections.push(connection);
return connection;
}
}
// Stubbing out the createConnetion method to ensure that we use our class overrides.
const createConnection = stub(typeorm, 'createConnection').callsFake(async function (optionsOrName:typeorm.ConnectionOptions) {
const connectionName = typeof optionsOrName === "string" ? optionsOrName : "default";
const options = optionsOrName instanceof Object ? optionsOrName : await typeorm.getConnectionOptions(connectionName);
return new ConnectionManager().create(options).connect();
});
export default createConnection({
name: 'test',
type: 'postgres',
entities: Object.values(entities)
} as typeorm.ConnectionOptions);
import 'source-map-support/register';
import * as chai from 'chai';
import * as sinonChai from 'sinon-chai';
import { ItemRepository } from './../src/repository'
import StubConnection from './dbUtility';
chai.use(sinonChai);
const { expect } = chai;
describe('Connection', async () => {
let connection, Item;
before(async () => {
connection = await StubConnection;
Item = connection.getCustomRepository(ItemRepository);
})
it('...', async () => {
// Do some stuff with Item
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment