React ES6 with chai/sinon:组件中的单元测试 XHR

React ES6 with chai/sinon: Unit testing XHR in component

我有一个 React 实用程序组件,它读取 URL:

的内容
'use strict';

export class ReadURL {

  getContent = (url) => {
      return new Promise((resolve, reject) => {
console.log('Promise')
          let xhr = new XMLHttpRequest();

          xhr.open("GET", url, false);
          xhr.onreadystatechange = () => {
console.log('onreadystatechange', xhr.readyState)
              if (xhr.readyState === 4) {
                  if (xhr.status === 200 || xhr.status == 0) {
console.log('200')
                      var allText = xhr.responseText;
                      resolve(allText);
                  } else {
                      reject('ajax error:' + xhr.status + ' ' + xhr.responseText);
                  }
              }
          };
          xhr.send(null);
      });
  };

}

我一直在尝试使用 Sinon 的 useFakeXMLHttpRequest() 对 xhr 进行存根,但无论我如何尝试,我都无法真正处理它 - 它目前以误报通过,但从未收到onreadystatechange 事件。 我尝试过使用 XHR 和 Axios 包以及本机 XMLHttpRequest,将请求包裹在承诺中而不是包裹在承诺中,一大堆不同的技巧,并阅读了无数的博客文章、文档和 SO 问题,我正在失去意志live...组件本身完美运行。

我已经设法使用 promises 和存根模块依赖项进行测试,但这让我很困惑。

这是测试:

import chai, { expect } from 'chai';
import sinon, { spy } from 'sinon';

import {ReadURL} from './ReadURL';


describe('ReadURL', () => {

  beforeEach(function() {

    this.xhr = sinon.useFakeXMLHttpRequest();

    this.requests = [];
    this.xhr.onCreate = (xhr) => {
console.log('xhr created', xhr)
      this.requests.push(xhr);
    };

    this.response = 'Response not set';
  });

  afterEach(function() {
    this.xhr.restore();

    this.response = 'Response not set';
  });

  it('should get file content from an xhr request', () => {
    const readURL = new ReadURL(),
          url = 'http://dummy.com/file.js',
          urlContent = `<awe.DisplayCode
            htmlSelector={'.awe-login'}
            jsxFile={'/src/js/components/AncoaAwe.js'}
            jsxTag={'awe.Login'}
            componentFile={'/src/js/components/Login/Login.js'}
          />`;

    readURL.getContent(url).then((response) =>{
console.log('ReadURL-test response', response)
            expect(response).to.equal(urlContent);
          });


    window.setTimeout(() => {
console.log('ReadURL-test trigger response')
      this.requests[0].respond(200,
        {
          'Content-Type': 'application/json'
        },
        urlContent
      )
    , 10});

  });

});

console.log('xhr created', xhr) 被触发,输出确认这是一个 sinon useFakeXMLHttpRequest 请求。

我已经创建了应用程序的存储库,其中包含查看组件功能所需的最低限度: https://github.com/DisasterMan78/awe-testcase

我目前没有在线样本,因为我不知道 运行 测试过任何在线沙箱。如果我能找到相应的服务,我会尝试添加失败概念的证明。

欧比旺-克诺比帮帮我。你是我唯一的希望!

嗯,那很有趣。在完成一个较旧的项目后,我今天又回到了它,但它仍然花了我太长时间。愚蠢的,小的语法错误。当然...

有两个严重错误。

首先,为了完成承诺,done 需要作为参数传递给测试的 it() 函数的函数:

it('should get file content from an xhr request', (done) => {
  ...
}

现在我们可以用 done 完成承诺:

    ...
    readURL.getContent(url)
      .then((response) => {
        expect(response).to.equal(this.response.content);
        done();
      })
      .catch((error) => {
console.log(error);
        done();
      });
    ...

我阅读的 none 文档或文章似乎以某种方式标记了这一点,但其中很少有人也在处理 promises,而我的 ExtractTagFromURL 测试也依赖于 promises 不需要这个,但我已经确认它对这个测试绝对至关重要。

在 promise 正常工作的情况下,respond() 调用不需要超时:

    ...
    this.requests[0].respond(this.response.status,
      {
        'Content-Type': this.response.contentType
      },
      this.response.content
    );
    ...

最后,我最大的问题是,为了正确设置和读取 thisthis.requests 和其他共享属性的值,[=20= 的函数参数] 和 afterEach() 需要使用箭头语法:

  ...
  beforeEach(() => {
    ...
  }
  ...

Github 上的简化测试用例已更新、通过并可以从 https://github.com/DisasterMan78/awe-testcase

中克隆

我想这使我成为 Obi Wan-Kenobe,是吧?

如有需要,请随时要求澄清!