2017-01-13 17 views
2

Я занимаюсь разработкой в ​​React на некоторое время для своей работы, но в последнее время мне было предложено получить некоторые приложения в ~ 100% тестовом покрытии с использованием Стамбула. За последние несколько дней я написал более 160 тестов для этого приложения, но я не смог охватить некоторые части моего кода. У меня больше всего проблем, связанных с вызовами AJAX, обратными вызовами setTimeout и компонентами, которые требуют, чтобы другой компонент работал правильно. Я прочитал несколько вопросов о том, что ничего не получилось, и я считаю, что это потому, что я приближаюсь к этому неправильно. Я использую Enzyme, Chai утверждения, Mocha, покрытие в Стамбуле, sinon для шпионов, и рассматривал нок, так как я не могу заставить работать 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 просто модуль, который строит API JQuery звоните с помощью getJSON. Мой тест закрывает вызов функции, но его не покрывает обратный вызов .done, который можно увидеть здесь: enter image description here Итак, мой вопрос: как я могу правильно проверить .done? Если у кого-то есть статья, учебник, видео, все, что объясняет, как правильно тестировать методы компонентов, я бы очень признателен!

Второй вопрос: как я могу протестировать метод, который передается в качестве опоры для дочернего компонента? С требованием тестирования покрытия я должен проверить этот метод, но его единственная цель - передать дочерний компонент, который будет использоваться как onClick. Это нормально, но onClick зависит от другого вызова AJAX, возвращающего данные в дочернем компоненте. Мой первоначальный импульс состоял в том, чтобы просто использовать ферменты. Найти, что onClick и имитировать событие click, но элемент с этим onClick не существует, потому что вызов AJAX не возвратил данные в тестовую среду. Если вы прочли это, я приветствую вас. И если вы можете помочь, я благодарю вас!

+1

Тестирование того, что 'componentDidMount' бессмысленен; это повторное тестирование React и ваша тестовая среда. Первая часть тестирования 'getJSON' завершается и гарантирует, что она вызывается с правильными аргументами.Вы вернете объект с помощью функции «done» и убедитесь, что состояние установлено правильно, но это вызывает проблему, так как она закодирована, она вызывает «setState», которая является асинхронной. –

+0

@DaveNewton Извините, что на самом деле это был неправильный тест. Но я возьму этот компонентный тестDidMount. Может ли это сделать? – Jake

+0

@DaveNewton, а также, не использовал бы заглушку, чтобы исходная функция не запускалась, поэтому не получив этого покрытия для теста? – Jake

ответ

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); 

и, наконец, вы будете испытывать, если сделано функция дозвонились, как это:

expect(onDone.calledOnce)to.be.true 

С этим должно работать как и ожидалось. Если вам нужно больше опций, вы можете увидеть все опции rewire в GitHub.

BABEL

Если вы используете столпотворение, как transpiler вам нужно использовать Бабель-плагин-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') 
    }) 
}) 
+0

Это выглядит как решение, но у меня проблемы с последней строкой в ​​вашем верхнем примере. Это мой модуль sdk выглядит так: 'module.exports = { getJSON (uri, data) { return this.call ('get', uri, data); }, ' суть всего модуля: https://gist.github.com/Munsterberg/be8165312ab0c69284f72cae72de37b9 – Jake

+0

я вижу, в этом случае будет проще просто перемонтировать свой вызов функции, я буду обновлять мой ответ – damianfabian

+0

Когда я требуется мой модуль с 'rewire (path)' он ломает мои другие тесты компонентов, это предназначенное поведение? – Jake

 Смежные вопросы

  • Нет связанных вопросов^_^