Vincent Laude
Vincent Laude

Reputation: 53

Problem with e2e testing with NestJS TestingModule, GraphQL code first and TypeOrm

I'm in struggle since few days with e2e testing my NestJS application using GraphQL code first approach and TypeOrm.

I'm trying to create a TestingModule by injecting nestjs GraphQLModule with autoSchemaFile and I'm always getting the error "Schema must contain uniquely named types but contains multiple types named ...".

Here a reproduction of my bug with minimal code:

character.entity.ts:

import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
import { ObjectType, Field, ID } from 'type-graphql';

@Entity()
@ObjectType()
export class Character {
    @PrimaryGeneratedColumn()
    @Field(() => ID)
    id: string;

    @Column({ unique: true })
    @Field()
    name: string;
}

character.resolver.ts:

import { Query, Resolver } from '@nestjs/graphql';
import { Character } from './models/character.entity';
import { CharacterService } from './character.service';

@Resolver(() => Character)
export class CharacterResolver {
    constructor(private readonly characterService: CharacterService) {}

    @Query(() => [Character], { name: 'characters' })
    async getCharacters(): Promise<Character[]> {
        return this.characterService.findAll();
    }
}

character.module.ts:

import { Module } from '@nestjs/common';
import { CharacterResolver } from './character.resolver';
import { CharacterService } from './character.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Character } from './models/character.entity';

@Module({
    imports: [TypeOrmModule.forFeature([Character])],
    providers: [CharacterResolver, CharacterService],
})
export class CharacterModule {}

app.module.ts:

import { Module } from '@nestjs/common';
import { CharacterModule } from './character/character.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Connection } from 'typeorm';
import { GraphQLModule } from '@nestjs/graphql';

@Module({
    imports: [TypeOrmModule.forRoot(), GraphQLModule.forRoot({ autoSchemaFile: 'schema.gql' }), CharacterModule],
    controllers: [],
    providers: [],
})
export class AppModule {
    constructor(private readonly connection: Connection) {}
}

and finally: character.e2e-spec.ts:

import { INestApplication } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { TypeOrmModule } from '@nestjs/typeorm';
import { CharacterModule } from '../src/character/character.module';
import { GraphQLModule } from '@nestjs/graphql';

describe('CharacterResolver (e2e)', () => {
    let app: INestApplication;

    beforeAll(async () => {
        const module: TestingModule = await Test.createTestingModule({
            imports: [
                TypeOrmModule.forRoot(),
                GraphQLModule.forRoot({ playground: false, autoSchemaFile: 'schema.gql' }),
                CharacterModule,
            ],
        }).compile();

        app = module.createNestApplication();
        await app.init();
    });

    it('should create testing module', () => {
        expect(1).toBe(1);
    });

    afterAll(async () => {
        await app.close();
    });
});

And after running npm run test:e2e:

Schema must contain uniquely named types but contains multiple types named "Character".

      at typeMapReducer (../node_modules/graphql/type/schema.js:262:13)
          at Array.reduce (<anonymous>)
      at new GraphQLSchema (../node_modules/graphql/type/schema.js:145:28)
      at Function.generateFromMetadataSync (../node_modules/type-graphql/dist/schema/schema-generator.js:31:24)
      at Function.<anonymous> (../node_modules/type-graphql/dist/schema/schema-generator.js:16:33)
      at ../node_modules/tslib/tslib.js:110:75
      at Object.__awaiter (../node_modules/tslib/tslib.js:106:16)
      at Function.generateFromMetadata (../node_modules/type-graphql/dist/schema/schema-generator.js:15:24)

I don't find any other way to create a testing module with graphql code first approach on official doc or while googling... Am I missing something ?

Upvotes: 5

Views: 1614

Answers (1)

dan-klasson
dan-klasson

Reputation: 14230

Your ormconfig.json need to look like this:

  "entities": [
    "src/**/*.entity.js"
  ],
  "migrations": [
    "src/migration/*.js"
  ],
  "cli": {
    "migrationsDir": "src/migration"
  }

I.e you need to specify the entities being in the src, not dist folder. If not TypeGraphQL will generate the schema for each resolver twice. To get the generate and run migration commands to work you would have to setup a different ormconfig.json for your development environment.

Upvotes: 1

Related Questions