nestjs 中的开玩笑单元测试模拟 google oauthClient

jest unit test mock google oauthClient in nestjs

我目前正在使用 Jest 对 Nestjs 中的服务进行单元测试,其中之一是使用 google Oauth 服务。我的目标是验证来自 google 的令牌并获取电子邮件以继续该过程。有什么方法可以模拟或跳过身份验证过程和 return 模拟电子邮件吗?这是我的代码:

// ...other modules
import { google, Auth } from "googleapis";

export class GoogleAuthService {
    oauthClient: Auth.OAuth2Client;
    constructor(
        // ...some provider services
    ) {
        const clientID = this.configService.get("GOOGLE_AUTH_CLIENT_ID");
        const clientSecret = this.configService.get("GOOGLE_AUTH_CLIENT_SECRET");
        // how can I mock this?
        this.oauthClient = new google.auth.OAuth2(clientID, clientSecret);
    }

    async authenticate(token: string) {
        try {
            // or need to mock this?
            const tokenInfo = await this.oauthClient.getTokenInfo(token);
            const email = tokenInfo.email;
            // ...other code
        } catch (error) {
            throw new UnauthorizedException();
        }
    }
}
describle("AuthService unit test", () => {
    let authService: AuthService;
    beforeEach(async () => {
        const module = await Test.createTestingModule({
            providers: [
                GoogleAuthService,
                // ... other services
            ],
        }).compile();
        GoogleAuthService = await module.get(GoogleAuthService);
    });

    describe("google login", () => {
        it("should return a user", async () => {
            // don't know how to test the 'authenticate' service
            const mockedToken = "mockedToken";
            const result = await GoogleAuthService.authenticate(mockedToken);
            expect(typeof result).toEqual(User);
        });
    });
})

感谢帮助!!!

这是经过测试的工作代码。您只需从 googleapis 中模拟 google.auth.OAuth2。在下面的模拟中,我创建了只有 email 属性 的 User 对象,您需要根据您的项目要求添加更多属性。同样为了这里的完整性, authenticate() returns email 而不是 User 对象。根据您的项目进行更改:

jest.mock('googleapis', () => {
  const googleApisMock = {
    google: {
      auth: {
        // this is how to mock a constructor
        OAuth2: jest.fn().mockImplementation(() => {
          return {
            getTokenInfo: jest.fn().mockResolvedValue({
              email: testEmail
            })
          }
        })
      }
    }
  }
  return googleApisMock
})

const testEmail = 'lukk@gmail.com'

describe('AuthService', () => {
  let googleAuthService: GoogleAuthService
  beforeEach(async () => {
    const module = await Test.createTestingModule({
      providers: [
        GoogleAuthService
        // ... other services
      ]
    }).compile()
    googleAuthService = await module.get(GoogleAuthService)
  })

  describe('authenticate', () => {
    it('should return a user', async () => {
      const email = await googleAuthService.authenticate('any token')
      expect(email).toEqual(testEmail)
    })
  })
})

测试结果:

 PASS  src/auth/google-auth.service.spec.ts (9.391 s)
  AuthService
    authenticate
      ✓ should return a user (6 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        10.077 s
Ran all test suites related to changed files.