Austin
07/18/2022, 9:34 AMprisma.$transaction
, but the problem is that all subsequent queries need to be transaction-aware (and so needs to use the prisma object provided by the $transaction
callback). This means I need to control the prisma object being passed to my backend functions so that instead of the normal client, they get the transaction-aware client. Is there some clever way to do this?
The docs recommend mocking but I would strongly prefer transaction-rollback testing my backend functions. Any recommendations from the community? Thank you šAustin
07/20/2022, 8:37 PMAustin
07/21/2022, 11:09 AMdb
with a db.prisma
singleton and a db.set
function. Inside my playwright test function I call withData
and that function is defined as follows (which is heavily inspired by the prisma docs):
export async function withData(fn: () => Promise<void>) {
try {
await new PrismaClient().$transaction(async (prisma) => {
db.set(prisma)
await fn(prisma)
throw new Error('rollback trigger')
})
} catch (err: any) {
if (err.message != 'rollback trigger') throw err
}
Itās a bit like using a Singleton class as a poor-mans IOC Dependency Injection, since in my code Iām now calling db.prisma.user.create
, etc, and so donāt have to worry about receiving a prisma param for every function I write. And it does solve the transaction-aware prisma client problem when Iām calling just domain functions.
So far so good, but, when I try to spin up a dev server and hit an endpoint, Iām creating another client in that other process that is not transaction aware.
I also tried `prisma.$executeRaw`Begin;`` and Rollback;
instead of the $transaction
call, which I think wouldāve worked as well, but it also doesnāt solve the separate process dev server problem. I know other frameworks would have to deal with this, like Rails and Phoenix. Iām most familiar with Ecto, the Elixir ORM-like, which solves this on the adapter level. So, as a peer to other db adapters like pg, mysql, mongo, etc., they have a sqlsandbox, and I think they somehow only provide clients that are (a) transaction-aware, and (b) can somehow read each otherās transaction writes and/or are really just a single client to begin with? I need to investigate further.
(I really want to figure this out bc Iām in love with (a) the power of db-aware service-layer tests, and (b) the speed with which transaction-rollback tests achieve (a). I have read yalls docs on the docker database approach. Have done a thing like that before and itās fine enough, but it can get really slow at scale to try and reset the docker db per test or chunk of tests, and āundoingā the changes in an afterEach is a sad and tedious world š )Austin
07/21/2022, 11:24 AM