Jest.js 测试失败,测试中未调用方法

zbq4xfa0  于 2023-06-27  发布在  Jest
关注(0)|答案(2)|浏览(200)

我正在尝试测试下面定义的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)没有绑定到正确的示例?

jogvjijk

jogvjijk1#

你的jest.spyOn(usersService, 'getAuthExistingUser').mockImplementation(null)应该是jest.spyon(usersService, 'getAuthExistingUser').mockResolvedValue(null)。现在,您实际上调用的是const existingUser = await null,如果是这样的话,我假设jest会传入其他实现。最后,很可能您的!existingUser测试返回false,导致您的createUser方法永远不会被调用。

fiei3ece

fiei3ece2#

如果我正确理解了你的问题,我认为这里的问题是方法usersService.getAuthExistingUser没有被正确调用,或者没有使用正确的参数。现在,它连接到mock方法服务中的getAuthExistingUser,该服务没有返回它应该返回的值。我的意思是它给出了不正确的值。
所以在这里,我可以考虑让getAuthExistingUser在我们使用预期参数调用它时返回一个有效值。所以在这里我建议尝试一个看起来像这样的例子来更新你的测试。
我们使用mockResolvedValue来指定模拟方法的返回值,这样我们就可以确保测试按预期运行。

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(createdUser);

  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);
});

相关问题