Kelsey
Kelsey

Reputation: 21

TypeORM/NestJS "type "geography" does not exist" when running tests

Created a new entity column on a table that looks like this:

@Column({
    type: 'geography',
    spatialFeatureType: 'Point',
    srid: 4326,
    nullable: true,
  })
  geography: Point

I am configuring the test module using NestJS and TypeORM. Based on the source code here and here, it seems as though by default, TypeORM installs Postgis if a geography column is detected, but I keep getting this error: QueryFailedError: type "geography" does not exist.

Here is the configuration I have for the test module:

export const testingModule = (providers: Provider[]) => {
  return Test.createTestingModule({
    imports: [
      TypeOrmModule.forRootAsync({
        useFactory: () =>  {
      type: 'postgres',
      url: getEnv('DATABASE_URL'),
      dropSchema: true,
      autoLoadEntities: true,
      synchronize: true,
      logging: false,
      namingStrategy: new SnakeNamingStrategy(),
      keepConnectionAlive: false,
    },
        dataSourceFactory: async (options: any) => ... // returns datasource
        },
      }),
      TypeOrmModule.forFeature(
        Location,
      ),
      EventEmitterModule.forRoot(),
    ],
    providers,
  })
}

Am I missing something here?

I also tried using the dataSourceFactory to explicitly add Postgis using the data source, but I believe this isn't happening synchronously, so I think the line to install Postgis happens after the schema is created (which contains the geography column, hence the error).

This works as designed in our regular environments, but unable to get this to play nice with the testing module from NestJS.

Upvotes: 0

Views: 257

Answers (1)

Alfred Doh-Nani
Alfred Doh-Nani

Reputation: 46

Here's how I went about it. I first added manualInitialization to my data source config and set it to true. This prevents TypeOrmModule from automatically initializing the database.

 TypeOrmModule.forRootAsync({
          useFactory: () => {
            //N.B: I use process.env here instead of configService.get
            // because of e2e tests. process.env can be mutated and updated
            // with connection details for a testcontainer database
    
            return {
              type: 'postgres' as const,
              host: process.env.DB_HOST,
              port: parseInt(process.env.DB_PORT),
              username: process.env.DB_USERNAME,
              password: process.env.DB_PASSWORD,
              database: process.env.DB_NAME,
              autoLoadEntities: true,
              synchronize: IS_DEV,
              logging: false,
              manualInitialization: true, <------ HERE
            };
          },
        })

I did that because I wanted to initialize the database manually to prevent this:

I think the line to install Postgis happens after the schema is created (which contains the geography column, hence the error).

In my test file, in the beforeAll hook, I create the postgis extension before manually initializing the database as shown below:

 beforeAll(async () => {
    ........
    
         app = moduleFixture.createNestApplication();
  

     const datasourceService = app.get(DataSourceService);
        const datasource = datasourceService.getDatasource();
            try {
               await datasource.initialize();
     HERE ----> await datasource.query(`CREATE EXTENSION IF NOT EXISTS "postgis"`);
            } catch (error) {
              console.error(error);
            }
            await app.init();
    
    ......
    });

I ran into the error: QueryFailedError: extension "postgis" is not available. The extension must first be installed on the system where PostgreSQL is running.

So I ran brew install postgis (I'm on a Mac. It installed a ton of packages.), and then I reran the test.

Upvotes: 0

Related Questions