chax-at / transactional-prisma-testing

Provides an easy way to execute database tests in a transaction that will be rolled back after each test for fast testing
MIT License
36 stars 1 forks source link

Started getting "savepoint transactional_testing_X does not exist" errors since v1 #6

Closed DimosthenisK closed 1 year ago

DimosthenisK commented 1 year ago

I'm not quite sure what happened, but exactly the same code throws an error in v1 and doesn't in v0.5.0, using prisma v4.15.0. image Happened in two different projects that use this library.

This is the code that builds the tests:

import { TestingModule, TestingModuleBuilder } from '@nestjs/testing';

import { AuthenticationService } from '../../../src/user/authentication/authentication.service';
import { ConfigService } from '@nestjs/config';
import { PostgreSqlContainer } from 'testcontainers';
import { PrismaService } from '../../../src/prisma/prisma.service';
import { PrismaTestingHelper } from '@chax-at/transactional-prisma-testing';
import { S3Service } from '../../../src/aws/s3/s3.service';
import { getRandomFreePort } from './get-random-free-port';
import { prismaReset } from './prisma-reset';
import { prismaSeed } from './prisma-seed';

export const buildTest = async (
  testID: string,
  testModuleFixture: TestingModuleBuilder,
) => {
  const pgPort = await getRandomFreePort();
  const dbUrl = `postgresql://${testID}:${testID}@localhost:${pgPort}/${testID}?schema=public`;
  const container = await new PostgreSqlContainer()
    .withExposedPorts({ container: 5432, host: pgPort })
    .withName(`${testID}-${pgPort}`)
    .withDatabase(testID)
    .withUsername(testID)
    .withPassword(testID)
    .start();

  await prismaReset(dbUrl);

  let prismaService = new PrismaService({
    datasources: { db: { url: dbUrl } },
  });
  await prismaService.$connect();

  const prismaTestingHelper = new PrismaTestingHelper(prismaService);
  prismaService = prismaTestingHelper.getProxyClient();

  const moduleFixture: TestingModule = await testModuleFixture
    .overrideProvider(ConfigService)
    .useValue({
      get: (value: string) =>
        value === 'DATABASE_URL' ? dbUrl : process.env[value],
    })
    .overrideProvider(PrismaService)
    .useValue(prismaService)
    .compile();

  const app = moduleFixture.createNestApplication();

  prismaService = app.get(PrismaService);

  await Promise.all([app.init(), prismaSeed(dbUrl)]);

  return {
    app,
    prismaService,
    beforeEach: async () => {
      await prismaTestingHelper.startNewTransaction({ timeout: 10000 });
    },
    afterEach: async () => {
      prismaTestingHelper.rollbackCurrentTransaction();
    },
    afterAll: async () => {
      await prismaService.$disconnect();
      await app.close();
      await container.stop();
    },
  };
};
Valerionn commented 1 year ago

Is it possible that you don't (completely) await all functions that call queries in your test? e.g. something like this

async function firstTest() {
  // ...
  const user = userService.loadUserFromDb(3); // note the missing "await"
}

async function secondTest() {
  // This test will fail now
}

where userService.loadUserFromDb looks like this:

public async loadUSerFromDb(id: number) {
  const user = await this.prismaService.user.findUnique({ where: { id } }); // note the "await" here
  return user;
}

I did publish a new pre-release version which improves the robustness of savepoint handling and logs a warning if the case mentioned above is detected. You can install it using

npm i -D @chax-at/transactional-prisma-testing@1.0.1-rc.1

This version fixes my own reproduction example from above at least (and logs a warning), please tell me if it's working for you as well (or maybe throws a different error at least).

Valerionn commented 1 year ago

The fix I mentioned above landed in 1.1.0, if you have time, you can try it out. Otherwise, you can stay on 0.6.0 which doesn't have implicit query transaction/savepoints (in case you don't need it and don't want to deal with debugging).

I'll close the issue for now, assuming it's fixed - but please let me know if you're still encountering any issues with the new version! (I don't know if you can re-open the issue, but just comment here or open another issue in this case if re-opening doesn't work)