NestJS 不会注入模拟模块,除非使用提供者令牌

问题描述 投票:0回答:1

我正在为沙盒项目编写单元测试,以测试 NestJS 中的一些内容。我遇到了一个问题,在单元测试中模拟时,采用注入服务 (

authService
) 的类显示为未定义。然而,当我使用提供者令牌注入它时,该服务似乎被正确地模拟并且不会显示为未定义。

我想这个问题是因为我没有正确制作模拟模块,因为这两种方法都可以在实践中找到(在单元测试之外)。只有在测试期间,我只能使用提供者令牌进行模拟,否则

authService
中的
AuthImplementation
显示为未定义。

这是我的模块 -

auth.module.ts

@Module({
    imports: [DatabaseModule],
    controllers: [AuthController],
    providers: [
        {
            provide: 'UserRepository',
            useFactory: (databaseAdapterService: DatabaseAdapterService) =>
                databaseAdapterService.getUserRepository(),
            inject: [DatabaseAdapterService],
        },
        {
            provide: AuthService,
            useFactory: (userRepository: UserRepository) => {
                return new AuthService(userRepository);
            },
            inject: ['UserRepository'],
        },
        {
            provide: AuthImplementation,
            useFactory: (authService: IAuthService) =>
                new AuthImplementation(authService),
            inject: [AuthService],
        },
    ]
})

AuthImplementation 类如下 -

auth.implementation.ts

import { Inject } from '@nestjs/common';
import { User } from 'src/domain/entities/user.entity';
import { AUTH_SERVICE, IAuthService } from 'src/domain/ports/auth-service.interface';

export class AuthImplementation {
    constructor(@Inject(AUTH_SERVICE) private readonly authService: IAuthService) { }
    
    // This approach, without the provider token, fails the unit tests because
    // authService shows up as undefined when mocked
    // constructor(private readonly authService: IAuthService) { }

    async register(username: string, password: string): Promise<User> {
        return this.authService.register(username, password);
    }

    async login(username: string, password: string): Promise<User | null> {
        return this.authService.login(username, password);
    }
}

仅当使用提供者令牌定义

provide
mockAuthService
字段时才有效的单元测试如下所示 -
auth.implementation.spec.ts

describe('AuthImplementation', () => {
    let authImplementation: AuthImplementation;
    let mockAuthService: jest.Mocked<IAuthService>;

    beforeEach(async () => {
        mockAuthService = {
            register: jest.fn(),
            login: jest.fn(),
        };

        const module: TestingModule = await Test.createTestingModule({
            providers: [
                AuthImplementation,
                {
                    // NOTE: This approach does not work
                    //provide: AuthService,

                    // NOTE: This works just fine
                    provide: AUTH_SERVICE,
                    useValue: mockAuthService,
                },
            ],
        }).compile();

        authImplementation = module.get<AuthImplementation>(AuthImplementation);
    });

    describe('register', () => {
        it('should register a user and return the user object', async () => {
            const username = 'testuser';
            const password = 'testpass';
            const mockUser = new User(new ObjectId(), username, password);

            mockAuthService.register.mockResolvedValue(mockUser);

            const result = await authImplementation.register(username, password);

            expect(mockAuthService.register).toHaveBeenCalledWith(username, password);
            expect(result).toBe(mockUser);
        });
    });

所以我的问题是,有没有办法直接引用测试模块中的AuthService,而不是必须定义一个提供者令牌(例如

export const AUTH_SERVICE = Symbol('AUTH_SERVICE');
)并在注入身份验证服务时使用它?为什么我可以逃脱:

provide: AUTH_SERVICE,

但不是

provide: AuthService,

在记录时在 AuthImplementation 中产生未定义的结果

authService

javascript unit-testing jestjs nestjs ts-jest
1个回答
0
投票

你解决这个问题了吗?我也有同样的问题

© www.soinside.com 2019 - 2024. All rights reserved.