【问题标题】:Unit testing for micro-frontend react application微前端反应应用的单元测试
【发布时间】:2021-10-12 18:35:58
【问题描述】:

我正在尝试为使用微前端架构的 react spa web 应用程序编写单元测试。我的第一步是为应用程序容器编写单元测试。

应用程序容器 react 组件使用一个 react-router 包含一个带有后续路由的开关来呈现主要内容区域中的组件。

每个应用程序都使用 JavaScript 运行时集成安装到应用程序容器。

我正在使用 React-Testing-Library 和 Jest 作为我的测试工具集的一部分。

我在互联网上到处搜索,但没有找到任何关于我遇到的问题的有用文章。他们中的大多数都展示了一个测试与我的场景无关的 Web 应用程序的演示。

我有 3 个问题需要一些指导。

  1. 由于微前端由多层组件组成,这些组件与身份验证和其他业务逻辑链接在一起。我应该只测试“页面组件”吗?还是应该从 App 组件开始测试整个应用程序容器?如果两者都不是,我应该如何测试这个应用程序?

  2. 为了简单起见,我尝试在页面组件级别进行测试以避免身份验证问题,但该组件包含来自 React Router 库的组件,并且 Jest 抱怨我不应该使用 <Link> 组件包含在<Router> 组件中。但是,<Router> 组件在运行时执行时出现在父组件级别。如何让 Jest “忽略”这个问题?

    我找不到允许我忽略此错误的配置。

  3. 由于问题 #2,我尝试通过渲染 <App> 组件来编写单元测试,但是该组件被传递到执行身份验证验证的高阶组件中。我如何才能专注于测试最终结果而不是身份验证 HOC 的功能,以便让组件呈现并让我的测试执行?

【问题讨论】:

  • 您问题中的术语微前端让我感到困惑。它有一个非常具体的含义 - 这实际上是一个 microfrontend 应用程序,还是您在询问有关测试反应组件的一般问题?一个微前端应用程序包含“胶水”代码,然后它包含一堆单独的组件(可以用各种框架编写,甚至是 vanilla js)。
  • 该应用程序是一个微前端应用程序。我只有为不使用身份验证或微前端的简单虚拟反应应用程序编写单元测试的经验;但是现在,我面临一个同时具有这两者的应用程序,这对我来说真的很困惑,所以我正在寻求一些帮助来理解我应该如何做到这一点。
  • 是什么让它成为微前端?如果整个应用程序都是用 react 编写的,并且组件的来源来自不同的地方/存储库,那么它就不是微前端,它只是一个 react 应用程序。第 2 点的答案很简单 - 在您的测试设置中,您将 Router 包裹在您的主题组件周围。

标签: reactjs micro-frontend react-testing


【解决方案1】:

一般来说,您应该测试每个组件,并且您应该只对包含在该组件中的逻辑进行断言

例如,假设您的 App 组件如下所示:

const App = () => (
   return (
     <Router>
       <Provider store={store}>
         <ThemeProvider>
            <Main/> <- the main entry point to your application
         </ThemeProvider>
       </Provider>
     </Router>
   );
);

那么,您唯一需要在 App 的测试套件中验证的是您正在呈现正确的层次结构。即,您不在乎 App 组件测试 Main 组件中包含的内容,您只关心 App 呈现 Main

那么怎么做呢?在您的测试套件中模拟Main 组件,并确保您的模拟在层次结构中的正确位置呈现。您还需要确保它使用正确的(可能是模拟的store)和ThemeProvider 呈现RouterProvider。同样,这些组件中的每一个的内容并不重要,只是 App 将它们呈现在适当的层次结构中,因为这是 App 包含的唯一逻辑。

一旦你开始跨越边界并尝试在App 的测试套件中验证Main 的内容,那么它会很快变得非常笨拙——也就是说,如果你更改Main 的实现,你将最终破坏了您的 App 测试,这是错误的 (IMO)。

我上面描述的是一个浅渲染测试策略。有些人反对这种策略(甚至 react-testing-library 本身也不提倡它)。我有相当多的编写和测试反应代码的经验,绝对提倡浅渲染/组件模拟。当然,每种情况都是独一无二的,它可能并不总是最好的策略,但在我遇到的几乎所有情况下,它都允许您将逻辑封装到可测试的块中,并使事情很容易删除/重构。

为了简单起见,我尝试在页面组件级别进行测试以避免身份验证问题,但该组件包含来自 React Router 库的组件,并且 Jest 抱怨我不应该使用未包含在零件。但是,在运行时执行时,组件存在于父组件级别。如何让 Jest “忽略”这个问题?

这是一个非常常见的场景,解决方案是提供您的组件在测试设置中工作所需的依赖项。

如果您的组件需要特定上下文(例如 Link 需要 NavigationContext),那么您的工作就是在测试设置中提供该上下文

如果您的组件需要封装在路由器中,那么您的测试设置如下所示:

import { render, screen } from '@testing-library/react' 
import { Router } from 'react-router-dom';
import { MySubjectComponent } from './MySubjectComponent';

it('should show my component with a Link',() => {
  // provide a Router in the test fixture because you
  // know MySubjectComponent needs it
  render(
    <Router>
      <MySubjectComponent/>
    </Router>
  );
});

我如何才能专注于测试最终结果而不是身份验证 HOC 的功能,以便我可以渲染组件并执行我的测试?

无论您尝试测试什么,答案总是相同的 - 模拟依赖项。

不过,请小心。我可能会提倡将组件与它们在 HOC 中的行为分开测试。请记住,HOC 的唯一工作是为组件提供 props。您可以轻松地将这些道具直接提供给测试套件中的组件,以查看它的行为方式,而无需使用 HOC。

要测试 HOC,您需要模拟 HOC 的依赖项(用于执行身份验证的函数、请求和响应),并传入一个模拟组件,您可以对以下 props 进行简单断言HOC 传递给它。

好的测试是我可以谈论几周的事情。

【讨论】:

    猜你喜欢
    • 2017-09-24
    • 1970-01-01
    • 2018-12-20
    • 2016-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-17
    • 2020-08-27
    相关资源
    最近更新 更多