【问题标题】:How do you mock Auth0 MangementClient using jest?您如何使用 jest 模拟 Auth0 MangementClient?
【发布时间】:2021-11-11 13:57:38
【问题描述】:

这也是Auth0 node-auth0 library上的一个问题。用例是我使用 Auth0 create Actions APITerraform 并希望能够针对 Actions 编写测试。

在此示例中,我希望能够在不使用实际值的情况下测试 onExecutePostLogin

// auth0-post-login.js

exports.onExecutePostLogin = async (event, api) => {
  const userId = event.user.user_id

  const ManagementClient = require('auth0').ManagementClient
  const management = new ManagementClient({
    domain: event.secrets.domain,
    clientId: event.secrets.clientId,
    clientSecret: event.secrets.clientSecret,
    audience: `https://${event.secrets.domain}/api/v2/`,
    scope: 'read:users',
  })

  const params = { id: userId, page: 0, per_page: 50, include_totals: false }
  let userPermissions = await management.getUserPermissions(params)
  const map = require('array-map')
  const permissions = map(userPermissions, function(permission) {
    return permission.permission_name
  })

  api.accessToken.setCustomClaim('https://example.com/access', permissions.join(' '))
}

其中一个主要问题是像getUserPermissions 这样的函数是通过它们的实用程序包装器创建的:

utils.wrapPropertyMethod(ManagementClient, 'getUserPermissions', 'users.getPermissions');

这会导致 jest 在查找函数时遇到问题。

【问题讨论】:

    标签: jestjs auth0


    【解决方案1】:

    为了获得像getUserPermissions 这样的功能,我需要重写ManagementClient 的实现。这让我可以将getUserPermissions 定义为模拟函数。

    import { onExecutePostLogin } from './auth0-post-login'
    
    const mockManagementClient = jest.fn()
    const mockGetUserPermissions = jest.fn()
    
    jest.mock('auth0', () => {
      return {
        ManagementClient: (opts) => {
          mockManagementClient(opts)
          return {
            getUserPermissions: (params) => {
              return mockGetUserPermissions(params)
            },
          }
        },
      }
    })
    
    describe('onExecutePostLogin', () => {
      const mockSetCustomClaim = jest.fn()
    
      beforeEach(() => {
        mockSetCustomClaim.mockClear()
        mockManagementClient.mockClear()
        mockGetUserPermissions.mockClear()
        mockGetUserPermissions.mockReturnValue([
          {
            permission_name: 'read:foo',
          },
          {
            permission_name: 'update:bar',
          },
        ])
      })
    
      const event = {
        user: {
          user_id: 'abcd123',
        },
        secrets: {
          domain: 'test-example.us.auth0.com',
          clientId: 'a-client-id',
          clientSecret: 'a-client-secret',
        },
      }
    
      const api = {
        accessToken: {
          setCustomClaim: mockSetCustomClaim,
        },
      }
    
      it('initializes a ManagementClient', async () => {
        await onExecutePostLogin(event, api)
    
        expect(mockManagementClient).toHaveBeenCalledWith({
          domain: event.secrets.domain,
          clientId: event.secrets.clientId,
          clientSecret: event.secrets.clientSecret,
          audience: `https://${event.secrets.domain}/api/v2/`,
          scope: 'read:users',
        })
      })
    
      it('gets users permissions', async () => {
        await onExecutePostLogin(event, api)
    
        expect(mockGetUserPermissions).toHaveBeenCalledWith(
          { id: event.user.user_id, page: 0, per_page: 50, include_totals: false },
        )
      })
    
      it('sets custom claims', async () => {
        await onExecutePostLogin(event, api)
    
        const expectedPermissions = 'read:foo update:bar'
        expect(mockSetCustomClaim).toHaveBeenCalledWith(
          'https://example.com/access', expectedPermissions,
        )
      })
    })
    

    【讨论】:

      【解决方案2】:

      我做了类似于 stsmurf 的事情来模拟 Auth0 方法的响应。

      我有一个文件,其中存储了我的帮助方法,例如“按名称查找角色”

      // helper.ts
      
      import { ManagementClient } from 'auth0';
      
      export const getRoleByName = async (roleName: string) => {
        const api = new ManagementClient({
          clientId: clientId,
          clientSecret: clientSecret,
          domain: domain,
        });
      
        const roles = await api.getRoles();
        const role = roles.find((r) => r.name == roleName);
        if (!role) throw new Error('Role not found');
      
        return role;
      };
      
      // helper.test.ts
      
      import { Role } from 'auth0';
      
      import { getRoleByName } from './helpers';
      
      const mockGetRoles = jest.fn();
      jest.mock('auth0', () => {
        return {
          ManagementClient: jest.fn().mockImplementation(() => {
            return {
              getRoles: mockGetRoles,
            };
          }),
        };
      });
      
      describe('Get role', () => {
        beforeAll(() => {
          const dummyRoles: Role[] = [
            { id: 'fake_id_1', description: 'Fake role nr 1', name: 'Fake Role 1' },
            { id: 'fake_id_2', description: 'Fake role nr 2', name: 'Fake Role 2' },
          ];
          mockGetRoles.mockImplementation(() => dummyRoles);
        });
      
        it('can return a role if it exists', async () => {
          const expectedResult: Role = {
            id: 'fake_id_1',
            description: 'Fake role nr 1',
            name: 'Fake Role 1',
          };
          const result = await getRoleByName('Fake Role 1');
      
          expect(expectedResult).toEqual(result);
        });
      
        it('will throw an error when a role is not found', async () => {
          await expect(getRoleByName('Fake Role 3')).rejects.toThrowError();
        });
      });
      

      【讨论】:

        猜你喜欢
        • 2020-05-17
        • 2019-02-02
        • 1970-01-01
        • 2018-01-26
        • 2020-07-04
        • 2017-09-30
        • 1970-01-01
        • 2018-02-13
        • 2018-12-25
        相关资源
        最近更新 更多