Last active
August 8, 2020 08:07
-
-
Save dfee/297b14ee9ed4621447205ea82c5a12cd to your computer and use it in GitHub Desktop.
Example of auto-rollback transactions with Mikro-Orm for testing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
Connection, | |
EntityManager, | |
IDatabaseDriver, | |
MikroORM, | |
} from "@mikro-orm/core"; | |
import { PostgreSqlDriver } from "@mikro-orm/postgresql"; | |
import { getConfig } from "../config"; | |
import { UserEntity } from "../entities"; | |
type TxOptions<T extends IDatabaseDriver<Connection>> = { | |
em: EntityManager<T>; | |
inner: (em: EntityManager<T>) => Promise<void>; | |
outer: (em: EntityManager<T>) => Promise<void>; | |
}; | |
const tx = async <T extends IDatabaseDriver<Connection>>({ | |
em, | |
inner: cbInner, | |
outer: cbOuter = () => Promise.resolve(), | |
}: TxOptions<T>) => { | |
const rollback = Symbol("rollback"); | |
try { | |
await em.transactional(async (emOuter) => { | |
await emOuter.transactional(async (emInner) => { | |
await cbInner(emInner as EntityManager<T>); | |
}); | |
await cbOuter(emOuter as EntityManager<T>); | |
throw rollback; | |
}); | |
} catch (e) { | |
if (e !== rollback) { | |
throw e; | |
} | |
} | |
}; | |
describe("create user in inner transaction, find it in outer transaction, and rollback to an empty db", () => { | |
const config = getConfig(); | |
let orm: MikroORM<PostgreSqlDriver>; | |
beforeAll(async () => { | |
orm = await MikroORM.init(config); | |
}); | |
afterAll(async () => { | |
await orm.close(); | |
}); | |
it("should create a user", async () => { | |
const user = new UserEntity({ | |
emailAddress: "[email protected]", | |
}); | |
await tx({ | |
em: orm.em, | |
inner: async (em) => { | |
const userRepository = em.getRepository(UserEntity); | |
userRepository.persist(user); | |
}, | |
outer: async (em) => { | |
const retrieved = await em | |
.getRepository(UserEntity) | |
.findOneOrFail(user.id); | |
expect(retrieved).toEqual(user); | |
}, | |
}); | |
}); | |
}); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment