2

为了我的工作,我已经在 React 中开发了一段时间,但最近我被要求使用伊斯坦布尔让一些应用程序达到 ~100% 的测试覆盖率。在过去的几天里,我已经为这个应用程序编写了 160 多个测试,但我无法覆盖我的代码的某些部分。在涉及 AJAX 调用、setTimeout 回调和需要另一个组件才能正常运行的组件方法时,我遇到了最大的麻烦。我已经阅读了几个 SO 问题无济于事,我相信那是因为我错误地处理了这个问题。我正在使用 Enzyme、Chai 断言、Mocha、Istanbul coverage、sinon for spies,并且正在考虑 nock,因为我无法让 sinon fakeServer 工作。

这是有问题的组件方法:

_getCategoriesFromServer() {
const _this = this;
sdk.getJSON(_this.props.sdkPath, {
    itemsperpage: 10000
}).done(function(data) {
    _this.setState({
        isLoaded: true,
        categories: _this.state.categories.concat(data)
    });
});

}

这是该组件的测试:

 it('should call _getCategoriesFromServer', () => {
    sinon.spy(CategoryTree.prototype, '_getCategoriesFromServer');
    wrapper = mount(<CategoryTree {...props} />);
    expect(CategoryTree.prototype._getCategoriesFromServer.calledOnce).to.be.true;
});

sdk 只是一个使用 getJSON 构造 jQuery API 调用的模块。我的测试涵盖了函数调用,但它没有涵盖此处看到的 .done 回调:在此处输入图像描述 所以我的问题是,我怎样才能正确测试 .done?如果有人有文章、教程、视频以及任何解释如何正确测试组件方法的内容,我将不胜感激!

第二个问题是,我该如何测试一个作为道具传递给子组件的方法?根据测试覆盖率要求,我必须对该方法进行测试,但其唯一目的是传递给子组件以用作 onClick。这很好,但是 onClick 依赖于另一个 AJAX 调用在子组件中返回数据。我最初的冲动是只使用酶 .find 来定位 onClick 并模拟点击事件,但是带有 onClick 的元素不存在,因为 AJAX 调用没有在测试环境中带回数据。如果你已经读到这里,我向你致敬。如果你能帮忙,我谢谢你!

4

1 回答 1

5

您可以使用 rewire ( https://github.com/jhnns/rewire ) 来测试您的组件,如下所示:

// let's said your component is ListBox.js
var rewire = require("rewire");
var myComponent = rewire("../components/ListBox.js");

const onDone = sinon.spy()
const sdkMock = {
    getJSON (uri, data) {
       return this.call('get', uri, data);
    },
    call: function (method, uri, data) {
       return { done: function(){ onDone() } }
    }
};
myComponent.__set__("sdk", sdkMock);

最后,您将测试 done 函数是否像这样调用:

expect(onDone.calledOnce)to.be.true

这样应该可以按预期工作。如果您需要更多选项,您可以在 GitHub 中查看所有 rewire 选项。

通天塔

如果你使用 babel 作为转译器,你需要使用 babel-plugin-rewire( https://github.com/speedskater/babel-plugin-rewire ) 你可以像这样使用它:

sdk.js

function call(method, uri, data) {
   return fetch(method, uri, data);
}
export function getJSON(uri, data) {
   return this.call('get', uri, data);
}

yourTest.js

import { getJSON, __RewireAPI__ as sdkMockAPI } from 'sdk.js';

describe('api call mocking', function() {
   it('should use the mocked api function', function(done) {
      const onDone = sinon.spy()
      sdkMockAPI.__Rewire__('call', function() {
         return { done: function(){ onDone() } }
      });
      getJSON('../dummy.json',{ data: 'dummy data'}).done()
      expect(onDone.calledOnce)to.be.true
      sdkMockAPI.__ResetDependency__('call')
   })
})
于 2017-01-16T10:53:50.407 回答