使用React进行Jasmine功能测试

时间:2018-10-25 23:40:37

标签: javascript reactjs jasmine

有人可以解释将Jasmine测试运行器集成到React应用程序中的正确方法(不添加Karma)吗?我将测试用例部署到电视上,并在电视机上运行独立的规范运行器。我必须内联并编译JS,这是我遇到麻烦的地方。我最终手动将jasmine.js,jasmine-html.js和boot.js文件串联到jasmine-all.js文件中,并插入如下调用以定义jasmineRequire:

jasmineRequire = getJasmineRequireObj();

这恰好在内联jasmine-html.js之前。然后,我在React根组件中添加了一个代码片段,以像这样加载整个内容:

  componentDidMount() {
   import('./jasmine/lib/jasmine-3.2.1/jasmine-all')
     .then(() => {return import('./spec/MyAppSpec');});
  }

我在这里使用动态导入来保证执行顺序。这个想法是允许应用程序加载,然后加载测试运行器,然后最终加载功能测试,这些测试将整个应用程序作为一个整体。这些测试会将关键事件和输入发送给应用程序,就像最终用户一样。

我知道有一种不太麻烦的方法可以做到这一点,但我无法弄清楚。我想以正确的方式执行此操作,以便可以正确包含任何规范帮助程序文件,这些文件目前已直接导入到我的规范文件中。任何指导都将不胜感激!

1 个答案:

答案 0 :(得分:3)

即使对诸如API请求之类的所有异步操作都进行了存根,也无法保证应用程序在根组件componentDidMount中达到了稳定状态。应该以相反的方式完成,即在测试中初始化应用程序,然后等待其稳定。

Jasmine中没有用于功能/端到端测试的内置功能,必须从头开始编写。

类似于:

async function waitForElement(selector, parent = document, timeout = 2000) {
  let isTimeout;

  setTimeout(() => {
    isTimeout = true;
  }, timeout);

  let el;
  while (!(el = parent.querySelector(selector))) {
    if (isTimeout) throw new Error('timeout');
    await new Promise(resolve => setTimeout(resolve, 50));
  }

  return el;
}

const root = document.getElementById('root');
beforeEach(() => {
  ReactDOM.render(<App/>, root);
});

afterEach(() => {
  ReactDOM.unmountComponentAtNode(root);
});

it('should have foo child', async () => {
  const foo = await waitForElement('div.foo', root, 5000);
  expect($(foo).text()).toContain('foo text');
});  

测试是基于承诺的,并且依赖于等待结果出现在DOM中,因为这可能是异步发生的。

waitForElement仅作为参考提供,因为它不足以进行实际的E2E测试;需要querySelector(可以用jQuery增强)或自定义谓词功能不支持的高级选择器。

这是E2E框架(如TestCafe和Protractor)应具有的功能,此功能的可用性与用于单元测试的框架不同。例如。 TestCafe具有reusable and chainable selectors,可以在需要元素的位置进行隐式处理。