5
votes

Trying to unit test. Got following error:

TypeError: Cannot read property 'prototype' of undefined

export class UserService {

constructor(@InjectRepository(User) private readonly userRepository: Repository < User>) { }

spec.ts:

describe('AuthController', () => {
let authController: AuthController;
let authService: AuthService;
let mockRepository = {

};
beforeEach(async () => {
    const module = await Test.createTestingModule({
        imports: [
            TypeOrmModule.forFeature([User]),
        ],
        controllers: [AuthController],
        providers: [AuthService, {
            provide: getRepositoryToken(User),
            useValue: mockRepository
        }]
    }).compile()
    authService = module.get<AuthService>(AuthService);
    authController = module.get<AuthController>(AuthController)
});

Can someone share a solution please?

MORE INFO:

So seems like its something wrong with typeorm

beforeEach(async () => {
    const module = await Test.createTestingModule({

    }).compile()
    authService = module.get<AuthService>(AuthService);
    authController = module.get<AuthController>(AuthController)
});

With this code I'm getting exact the same error. So only problem is adding typeorm to this test Module.

So it fails because of dependency: AuthController->AuthService->UserService->TypeORM

Btw just checked UserService using API with Postman and it works fine.

Still no result:

 module = await Test.createTestingModule({
        controllers: [AuthController],
        components: [
            {
                provide: AuthService,
                useValue: {}
            },
            {
                provide: UserService,
                useValue: {}
            },
            {
                provide: getRepositoryToken(User),
                useValue: {}
            }
        ],
        providers: [
            {
                provide: AuthService,
                useValue: {}
            },
            {
                provide: UserService,
                useValue: {}
            },
            {
                provide: getRepositoryToken(User),
                useValue: {}
            }
        ]
    }).compile()
    this.authController = module.get<AuthController>(AuthController)

Also

class AuthServiceMock {
    logIn(userName) {
        return { id:100, isDeleted:false, login:"login", password:"password"};
    }

    signUp() {
        return { expireIn: 3600, token:"token" };
    }
}

describe('AuthController', () => {
let module: TestingModule;
let authController: AuthController;
let authService: AuthService;

beforeEach(async () => {
    module = await Test.createTestingModule({
        controllers: [AuthController],
        components: [

        ],
        providers: [
            {
                provide: AuthService,
                useClass: AuthServiceMock
            },
        ]
    }).compile()
    this.authController = module.get<AuthController>(AuthController)
});
3
Did you solve it somehow? I"m having the same issue - alex88
@alex88 yes. I recreated project and copied all old files to new. Seems like it was some typeorm bug. - rankery

3 Answers

3
votes

I looked at the project you provided in a comment under Kim Kern (https://github.com/rankery/wof-server)

You are using a barrel file (src/user/index.ts), exporting the UserModule

export * from './user.module';

I guess you are using this barrel file to import the module later on.

Now, every time the content of the barrel file is imported , the code contained in the built version of your src/user/user.module.ts is executed, which include the decoration of the UserModule class, which in turns will make Typeorm try to build a Repository, which causes the error.

You should remove this export from src/user/index.ts (or simply delete the file) and fix the broken imports caused by this removal and it should work.

0
votes

I just passed the User entity to Repository and it works.

@Injectable()
export class UserService {
    constructor(
        @InjectRepository(User)
        private readonly userRepository: Repository<User>
    ) { }

}

Checkout docs from here: https://docs.nestjs.com/techniques/database. They have pretty good docs.

0
votes

When you import TypeOrmModule.forFeature(...) you also have to import TypeOrmModule.forRoot(...). But in a unit test, you probably don't want to work with your database but instead mock out all dependencies.

Your controller should not access the database directly, that's what the service is for. So if you want to test your controller and it only injects the service, you should only declare an AuthService mock and not import anything:

const module = await Test.createTestingModule({
    controllers: [AuthController],
    providers: [{
        provide: AuthService,
        useValue: authServiceMock
    }]
}).compile()

If you want to test your AuthService and it only injects the repository declare your mockRepository and leave everything else out.