Nest 无法解析 AuthService 的依赖项(AuthRepository,?)
Posted
技术标签:
【中文标题】Nest 无法解析 AuthService 的依赖项(AuthRepository,?)【英文标题】:Nest can't resolve dependencies of the AuthService (AuthRepository, ?) 【发布时间】:2021-01-28 03:41:58 【问题描述】:我正在尝试在我的项目中实施 JWT。我已经按照https://www.npmjs.com/package/@nestjs/jwt#usage中的大纲进行了操作
auth.module.ts
import Module from '@nestjs/common';
import AuthService from './auth.service';
import AuthController from './auth.controller';
import TypeOrmModule from '@nestjs/typeorm';
import JwtModule from '@nestjs/jwt';
import AuthRepository from './auth.repository';
@Module(
imports: [
JwtModule.register( secret: process.env.JWT_SECRET || 'ABCDE12345' ),
TypeOrmModule.forFeature([AuthRepository]),
],
exports: [TypeOrmModule, AuthService],
providers: [AuthService],
controllers: [AuthController],
)
export class AuthModule
auth.service.ts
import Injectable, NotFoundException, UnauthorizedException from '@nestjs/common';
import InjectRepository from '@nestjs/typeorm';
import AuthEntity from './auth.entity';
import LoginDTO from './dto/login.dto';
import * as bcrypt from 'bcrypt';
import JwtService from '@nestjs/jwt';
import crypto from 'crypto';
import AuthRepository from './auth.repository';
// export interface FindWhereData
// readonly email: string;
// readonly password: string;
//
export interface LoginResponse
readonly token: string;
readonly refresh_token: string;
@Injectable()
export class AuthService
constructor(
@InjectRepository(AuthRepository)
private authRepository: AuthRepository,
private jwtService: JwtService
)
/**
* Login user service
*
* @param doc
*/
public async login(doc: LoginDTO): Promise<LoginResponse>
// verify user email
const user = await this.authRepository.findOne( email: doc.email );
if (!user)
throw new NotFoundException('Could not find user');
// verify password
const passwordsMatch = await this.passwordsAreEqual(doc.password, user.password);
if (!passwordsMatch)
throw new UnauthorizedException('Incorrect login credentials');
// generate JWT
const token = await this.jwtService.signAsync( id: user.id );
// create the refresh token
const refreshToken = crypto.randomBytes(256).toString('hex');
// store the refresh token
return
token: token,
refresh_token: refreshToken,
;
/**
* Generate a hashed password
*
* @param password
*/
public async hashPassword(password: string): Promise<string>
const salt = await bcrypt.genSalt();
return await bcrypt.hash(password, salt);
/**
* Compare password against an encrypted string
*
* @param password
* @param encryptedPassword
*/
public async passwordsAreEqual(password: string, encryptedPassword: string): Promise<boolean>
return await bcrypt.compare(password, encryptedPassword);
/**
* Find a record by column attribute and value
*
* @param queryObject
*
*/
public async findWhere(queryObject): Promise<AuthEntity>
const authEntity = await this.authRepository.findOne( where: queryObject );
if (!authEntity)
return null;
return authEntity;
public async findOne(id: string): Promise<AuthEntity>
return this.authRepository.findOne(id);
auth.repository.ts
import EntityRepository, Repository from "typeorm";
import AuthEntity from "./auth.entity";
@EntityRepository(AuthEntity)
export class AuthRepository extends Repository<AuthEntity>
app.module.ts
import Module from '@nestjs/common';
import AppController from './app.controller';
import AppService from './app.service';
import RouterModule from 'nest-router';
import routes from './routes';
import ConfigModule from '@nestjs/config';
import configuration from './config/configuration';
import TypeOrmModule from '@nestjs/typeorm';
import Connection from 'typeorm';
import AuthModule from './auth/auth.module';
@Module(
imports: [
RouterModule.forRoutes(routes),
ConfigModule.forRoot(
load: [configuration],
),
TypeOrmModule.forRoot(
type: 'postgres',
host: process.env.POSTGRES_HOST || 'localhost',
port: 5432,
username: process.env.POSTGRES_USERNAME || 'postgres',
password: process.env.POSTGRES_PASSWORD || 'password',
database: process.env.POSTGRES_DATABASE || 'service-auth',
autoLoadEntities: true,
synchronize: true,
),
AuthModule,
],
controllers: [AppController],
providers: [AppService],
)
export class AppModule
constructor(private readonly connection: Connection)
console.log('connection status: ' + connection.isConnected);
auth.service.spec.ts
import JwtModule, JwtService from '@nestjs/jwt';
import Test, TestingModule from '@nestjs/testing';
import AuthEntity from './auth.entity';
import AuthRepository from './auth.repository';
import AuthService from './auth.service';
describe('AuthService', () =>
let authService: AuthService;
let authRepository: AuthRepository;
const mockAuthRepository = () => (
login: jest.fn(),
);
beforeEach(async () =>
const module: TestingModule = await Test.createTestingModule(
providers: [
AuthService,
// JwtModule,
provide: getRepositoryToken(AuthRepository),
useFactory: mockAuthRepository,
,
provide: JwtService,
useValue:
signAsync: jest.fn(() => 'token'),
]
).compile();
authService = await module.get<AuthService>(AuthService);
authRepository = await module.get<AuthRepository>(AuthRepository);
);
/**
* Test that the service is defined
*/
it('should be defined', () =>
expect(authService).toBeDefined();
);
);
当我运行 npm run test
时,我收到以下错误消息:
FAIL src/auth/auth.service.spec.ts
● AuthService › should be defined
Nest can't resolve dependencies of the AuthService (AuthRepository, ?). Please make sure that the argument JwtService at index [1] is available in the RootTestModule context.
Potential solutions:
- If JwtService is a provider, is it part of the current RootTestModule?
- If JwtService is exported from a separate @Module, is that module imported within RootTestModule?
@Module(
imports: [ /* the Module containing JwtService */ ]
)
我知道经验丰富的 Node/Nest 开发人员可能很清楚该错误,但我无法弄清楚 RootTestModule 是什么以及如何导入 JwtModule。
我相信我已正确遵循设置,但将此 JwtModule 添加到 AuthService 会导致该服务在我的单元测试中未定义。
回购 https://github.com/marcuschristiansen/nestjs-auth
【问题讨论】:
【参考方案1】:您应该为JwtService
添加一个自定义提供程序,以便您可以模拟它。自定义提供程序可能看起来像
provide: JwtService,
useValue:
signAsync: jest.fn(() => 'token'),
告诉 Nest 注入一个具有 signAsync()
方法的对象,该方法在调用时返回字符串 'token'
,以便在您的测试中始终保持相同。
这个对象进入providers
数组,就像AuthRepository
模拟
【讨论】:
请查看我对 auth.service.spec.ts 的编辑现在获取 Nest 无法解决 AuthService (?, JwtService) 的依赖关系。请确保索引 [0] 处的参数 AuthRepository 在 RootTestModule 上下文中可用。AuthRepository
应该是 getRepositoryToken(AuthRepository)
以便您获得 Nest 期望的正确注入令牌
嗯,我觉得不错。您能否提供一个指向您的存储库的链接?
给你github.com/marcuschristiansen/nestjs-auth
您的 auth.service.spec
按预期运行。错误来自您的auth.controller.spec
,因为AuthService
没有在那里模拟,所以它正在寻找AuthSerivce
的依赖项。以上是关于Nest 无法解析 AuthService 的依赖项(AuthRepository,?)的主要内容,如果未能解决你的问题,请参考以下文章
NestJS 无法解析 AuthServices 的依赖关系
Nest 无法解析 PhotoService 的依赖关系(?)