我正在尝试测试下面定义的Passport策略。我正在使用Magic SDK进行身份验证。
magic.strategy.ts
import { Magic } from '@magic-sdk/admin'
import { Injectable, Logger } from '@nestjs/common'
import { ConfigService } from '@nestjs/config'
import { PassportStrategy } from '@nestjs/passport'
import { DoneFunc, Strategy } from 'passport-magic'
import { UserFromDid } from '../../types/magic.types'
import { UsersService } from '../../users/users.service'
@Injectable()
export class MagicStrategy extends PassportStrategy(Strategy, 'magic') {
private readonly logger = new Logger(MagicStrategy.name)
constructor(
private readonly config: ConfigService,
private readonly userService: UsersService
) {
const magic = new Magic(config.get('MAGIC_SECRET_KEY'))
super({
magicInstance: magic,
},
async function (user: UserFromDid, done: DoneFunc) {
const userMetadata = await magic.users.getMetadataByIssuer(user.issuer)
const existingUser = await userService.getAuthExistingUser(userMetadata.email)
let createdUser: { user_id: string }
if (!existingUser) {
console.log('TEST IS PASSING HERE')
createdUser = await userService.createUser({
email: userMetadata.email,
wallet_pubaddress: userMetadata.publicAddress,
last_login_at: user.claim.iat,
issuer: user.issuer,
})
console.log('CREATED USER', createdUser)
done(null, existingUser ? { user_id: existingUser.user_id } : createdUser)
} else {
if (user.claim.iat <= existingUser.last_login_at.getTime() / 1000) {
this.logger.error(`Replay attack detected for user ${user.issuer}`)
return done(null, false, {
message: `Replay attack detected for user ${user.issuer}}.`,
})
}
await userService.updateLastLogin(user.issuer, user.claim.iat)
return done(null, { user_id: existingUser.user_id })
}
},
)
}
}
我正在使用以下测试文件测试上述代码:
magic.strategy.spec.ts:
import { ConfigService } from '@nestjs/config'
import { Test, TestingModule } from '@nestjs/testing'
import { Request } from 'express'
import { PrismaService } from '../../prisma.service'
import { UsersService } from '../../users/users.service'
import { MagicStrategy } from './magic.strategy'
describe('MagicStrategy', () => {
let magicStrategy: MagicStrategy
let usersService: UsersService
let configService: ConfigService
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [MagicStrategy, UsersService, ConfigService, PrismaService],
})
.overrideProvider(UsersService)
.useValue({
getAuthExistingUser: jest.fn(),
createUser: jest.fn(),
})
.overrideProvider(ConfigService)
.useValue({ get: jest.fn() })
.compile()
magicStrategy = module.get<MagicStrategy>(MagicStrategy)
usersService = module.get<UsersService>(UsersService)
configService = module.get<ConfigService>(ConfigService)
})
describe('validate', () => {
it('should create a new user if the user does not exist', async () => {
const user = {
issuer: 'someissuer',
claim: {
iat: 1234567890,
},
}
const createdUser = { user_id: 'newuserid' }
const done = jest.fn()
jest.spyOn(usersService, 'getAuthExistingUser').mockResolvedValue(null)
jest.spyOn(usersService, 'createUser').mockResolvedValue({ user_id: 'user-id' })
await magicStrategy.authenticate({ headers: { authorization: 'bearer 1234556' } } as Request)
expect(configService.get).toHaveBeenCalledWith('MAGIC_SECRET_KEY')
expect(usersService.getAuthExistingUser).toHaveBeenCalledWith('email')
expect(usersService.createUser).toHaveBeenCalledWith({
email: 'email',
wallet_pubaddress: 'publicAddress',
last_login_at: user.claim.iat,
issuer: user.issuer,
})
expect(done).toHaveBeenCalledWith(null, createdUser)
})
})
})
但是,测试失败,出现以下错误:
Error: expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: {"email": "email", "issuer": "someissuer", "last_login_at": 1234567890, "wallet_pubaddress": "publicAddress"}
Number of calls: 0Jest
这很奇怪,因为方法usersService.getAuthExistingUser
确实被调用并传递了Assert。此外,我在mockFunction中添加了一些日志,可以看到日志。我还在magic.strategy.ts
文件中的createUser
语句后添加了日志,并调用了日志。
测试日志我在测试日志中看到了方法的两个控制台日志,如下所示:
FAIL src/auth/passport-strategies/magic.strategy.spec.ts
● Console
console.log
TEST IS PASSING HERE
at MagicStrategy.log (auth/passport-strategies/magic.strategy.ts:26:14)
console.log
CREATED USER { user_id: 'user-id' }
at MagicStrategy.log (auth/passport-strategies/magic.strategy.ts:33:14)
● MagicStrategy › validate › should create a new user if the user does not exist
expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: {"email": "email", "issuer": "someissuer", "last_login_at": 1234567890, "wallet_pubaddress": "publicAddress"}
Number of calls: 0
所以日志显示mockResolvedValue
确实在工作。我的下一个猜测是jest.spyOn(...., createUser)
没有绑定到正确的示例?
2条答案
按热度按时间jogvjijk1#
你的
jest.spyOn(usersService, 'getAuthExistingUser').mockImplementation(null)
应该是jest.spyon(usersService, 'getAuthExistingUser').mockResolvedValue(null)
。现在,您实际上调用的是const existingUser = await null
,如果是这样的话,我假设jest会传入其他实现。最后,很可能您的!existingUser
测试返回false
,导致您的createUser
方法永远不会被调用。fiei3ece2#
如果我正确理解了你的问题,我认为这里的问题是方法
usersService.getAuthExistingUser
没有被正确调用,或者没有使用正确的参数。现在,它连接到mock方法服务中的getAuthExistingUser
,该服务没有返回它应该返回的值。我的意思是它给出了不正确的值。所以在这里,我可以考虑让
getAuthExistingUser
在我们使用预期参数调用它时返回一个有效值。所以在这里我建议尝试一个看起来像这样的例子来更新你的测试。我们使用
mockResolvedValue
来指定模拟方法的返回值,这样我们就可以确保测试按预期运行。