测试 MSAL React 应用程序时模拟身份验证

问题描述 投票:0回答:2

我们的应用程序以标准方式封装在

@azure/msal-react
的 MSAL 身份验证模板中 - 关键代码段总结如下。

我们想使用反应测试库(或类似的东西)来测试应用程序的各个组件。当然,当要通过测试正确呈现诸如

SampleComponentUnderTest
之类的 React 组件(如下面的简单测试所示)时,它也必须包装在 MSAL 组件中。

是否有适当的方法来模拟 MSAL 身份验证过程以用于此类目的?无论如何,要在 MSAL 中包装待测组件并直接向该待测组件提供测试用户的凭据吗?任何对有用文档、博客文章、视频等的引用,为我们指明正确的方向,我们将不胜感激。

简单测试

test('first test', () => {
  const { getByText } = render(<SampleComponentUnderTest />);
  const someText = getByText('A line of text');
  expect(someText).toBeInTheDocument();
});

配置

export const msalConfig: Configuration = {
  auth: {
    clientId: `${process.env.REACT_APP_CLIENT_ID}`,
    authority: `https://login.microsoftonline.com/${process.env.REACT_APP_TENANT_ID}`,
    redirectUri:
      process.env.NODE_ENV === 'development'
        ? 'http://localhost:3000/'
        : process.env.REACT_APP_DEPLOY_URL,
  },
  cache: {
    cacheLocation: 'sessionStorage',
    storeAuthStateInCookie: false,
  },
  system: {
    loggerOptions: {
      loggerCallback: (level, message, containsPii) => {
        if (containsPii) {
          return;
        }
        switch (level) {
          case LogLevel.Error:
            console.error(message);
            return;
          case LogLevel.Info:
            console.info(message);
            return;
          case LogLevel.Verbose:
            console.debug(message);
            return;
          case LogLevel.Warning:
            console.warn(message);
            return;
          default:
            console.error(message);
        }
      },
    },
  },
};

主要应用程序组件

const msalInstance = new PublicClientApplication(msalConfig);

<MsalProvider instance={msalInstance}>
  {!isAuthenticated && <UnauthenticatedHomePage />}
  {isAuthenticated && <Protected />}
</MsalProvider>

未经身份验证的组件

const signInClickHandler = (instance: IPublicClientApplication) => {
  instance.loginRedirect(loginRequest).catch((e) => {
    console.log(e);
  });
};

<UnauthenticatedTemplate>
  <Button onClick={() => signInClickHandler(instance)}>Sign in</Button>
</UnauthenticatedTemplate>

受保护组件

<MsalAuthenticationTemplate
  interactionType={InteractionType.Redirect}
  errorComponent={ErrorComponent}
  loadingComponent={LoadingComponent}
>
    <SampleComponentUnderTest />
</MsalAuthenticationTemplate>
react-testing-library azure-ad-msal msal.js msal-react
2个回答
13
投票

关于 msal-react 下的组件测试,我遇到了与您相同的问题。 我花了几天时间才弄清楚如何实现正确的身份验证模拟。 这就是为什么我创建了一个包,您可以在这里找到它,它封装了所有样板代码:https://github.com/Mimetis/msal-react-tester

基本上,您可以在几行中执行多个场景(用户已登录、用户未登录、用户必须登录等...),无需配置任何内容,当然也无需在任何情况下访问 Azure AD案例:

describe('Home page', () => {

  let msalTester: MsalReactTester;
  beforeEach(() => {
    // new instance of msal tester for each test
    msalTester = new MsalReactTester();

    // spy all required msal things
    msalTester.spyMsal();
  });

  afterEach(() => {
    msalTester.resetSpyMsal();
  });

  test('Home page render correctly when user is logged in', async () => {

    msalTester.isLogged();

    render(
      <MsalProvider instance={msalTester.client}>
        <MemoryRouter>
          <Layout>
            <HomePage />
          </Layout>
        </MemoryRouter>
      </MsalProvider>,
    );

    await msalTester.waitForRedirect();

    let allLoggedInButtons = await screen.findAllByRole('button', { name: `${msalTester.activeAccount.name}` });
    expect(allLoggedInButtons).toHaveLength(2);
  });

  test('Home page render correctly when user logs in using redirect', async () => {

    msalTester.isNotLogged();
    render(
      <MsalProvider instance={msalTester.client}>
        <MemoryRouter>
          <Layout>
            <HomePage />
          </Layout>
        </MemoryRouter>
      </MsalProvider>,
    );

    await msalTester.waitForRedirect();

    let signin = screen.getByRole('button', { name: 'Sign In - Redirect' });
    userEvent.click(signin);

    await msalTester.waitForLogin();

    let allLoggedInButtons = await screen.findAllByRole('button', { name: `${msalTester.activeAccount.name}` });
    expect(allLoggedInButtons).toHaveLength(2);
  });



0
投票

我也对此感到好奇,但角度略有不同。我试图避免直接从 msal 中直接使用组件来乱扔代码库,以防我们想在某个时候更换身份提供者。实现此目的的主要方法是使用钩子作为抽象层,例如通过该钩子而不是 msal 组件库本身公开 isAuthenticated。

useAuth 挂钩将直接使用 MSAL 包。然而,对于包装器组件,我认为我们必须创建一个单独的组件,该组件返回 MsalProvider 或您选择的模拟身份验证提供程序。由于 MsalProvider 在底层使用了 useContext,我认为您不需要将其包装在另一个上下文提供程序中。

希望这些想法在您思考如何做到这一点时有所帮助。要知道这不是对您问题的直接答案。

© www.soinside.com 2019 - 2024. All rights reserved.