Поиск…
Основное утверждение
На самом базовом уровне модульное тестирование на любом языке предоставляет утверждения против некоторых известных или ожидаемых результатов.
function assert( outcome, description ) {
var passFail = outcome ? 'pass' : 'fail';
console.log(passFail, ': ', description);
return outcome;
};
Популярный метод утверждения выше показывает нам один быстрый и простой способ утверждать ценность в большинстве веб-браузеров и интерпретаторов, таких как Node.js, практически с любой версией ECMAScript.
Хороший модульный тест предназначен для проверки сдержанной единицы кода; обычно функция.
function add(num1, num2) {
return num1 + num2;
}
var result = add(5, 20);
assert( result == 24, 'add(5, 20) should return 25...');
В приведенном выше примере возвращаемое значение из функции add(x, y)
или 5 + 20
составляет, очевидно, 25
, поэтому наше утверждение 24
должно завершиться неудачей, и метод assert будет записывать строку «fail».
Если мы просто изменим ожидаемый результат утверждения, тест будет успешным, и результат будет выглядеть примерно так.
assert( result == 25, 'add(5, 20) should return 25...');
console output:
> pass: should return 25...
Это простое утверждение может гарантировать, что во многих разных случаях функция «добавить» всегда будет возвращать ожидаемый результат и не требует каких-либо дополнительных фреймворков или библиотек.
Более строгий набор утверждений будет выглядеть следующим образом (с помощью var result = add(x,y)
для каждого утверждения):
assert( result == 0, 'add(0, 0) should return 0...');
assert( result == -1, 'add(0, -1) should return -1...');
assert( result == 1, 'add(0, 1) should return 1...');
И консольный вывод будет следующим:
> pass: should return 0...
> pass: should return -1...
> pass: should return 1...
Теперь мы можем с уверенностью сказать, что add(x,y)
... должно возвращать сумму двух целых чисел . Мы можем развернуть их примерно так:
function test__addsIntegers() {
// expect a number of passed assertions
var passed = 3;
// number of assertions to be reduced and added as Booleans
var assertions = [
assert( add(0, 0) == 0, 'add(0, 0) should return 0...'),
assert( add(0, -1) == -1, 'add(0, -1) should return -1...'),
assert( add(0, 1) == 1, 'add(0, 1) should return 1...')
].reduce(function(previousValue, currentValue){
return previousValue + current;
});
if (assertions === passed) {
console.log("add(x,y)... did return the sum of two integers");
return true;
} else {
console.log("add(x,y)... does not reliably return the sum of two integers");
return false;
}
}
Unit Testing Promises с мокко, синонами, чаями и проксимиром
Здесь у нас есть простой класс для тестирования, который возвращает Promise
на основе результатов внешнего ResponseProcessor
, для выполнения которого требуется время.
Для упрощения будем считать, что метод processResponse
никогда не будет терпеть неудачу.
import {processResponse} from '../utils/response_processor';
const ping = () => {
return new Promise((resolve, _reject) => {
const response = processResponse(data);
resolve(response);
});
}
module.exports = ping;
Чтобы проверить это, мы можем использовать следующие инструменты.
Я использую следующий test
скрипт в файле package.json
.
"test": "NODE_ENV=test mocha --compilers js:babel-core/register --require ./test/unit/test_helper.js --recursive test/**/*_spec.js"
Это позволяет использовать синтаксис es6
. Он ссылается на test_helper
который будет выглядеть
import chai from 'chai';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import chaiAsPromised from 'chai-as-promised';
import sinonStubPromise from 'sinon-stub-promise';
chai.use(sinonChai);
chai.use(chaiAsPromised);
sinonStubPromise(sinon);
Proxyquire
позволяет нам вводить наш собственный заглушка вместо внешнего ResponseProcessor
. Затем мы можем использовать sinon
чтобы шпионить за sinon
методами. Мы используем расширение для chai
, что chai-as-promised
впрыскивает проверить , что ping()
обещание методы является fullfilled
, и что он в eventually
возвращает нужный ответ.
import {expect} from 'chai';
import sinon from 'sinon';
import proxyquire from 'proxyquire';
let formattingStub = {
wrapResponse: () => {}
}
let ping = proxyquire('../../../src/api/ping', {
'../utils/formatting': formattingStub
});
describe('ping', () => {
let wrapResponseSpy, pingResult;
const response = 'some response';
beforeEach(() => {
wrapResponseSpy = sinon.stub(formattingStub, 'wrapResponse').returns(response);
pingResult = ping();
})
afterEach(() => {
formattingStub.wrapResponse.restore();
})
it('returns a fullfilled promise', () => {
expect(pingResult).to.be.fulfilled;
})
it('eventually returns the correct response', () => {
expect(pingResult).to.eventually.equal(response);
})
});
Теперь вместо этого предположим, что вы хотите проверить что-то, что использует ответ от ping
.
import {ping} from './ping';
const pingWrapper = () => {
ping.then((response) => {
// do something with the response
});
}
module.exports = pingWrapper;
Для тестирования pingWrapper
мы используем
Как и прежде, Proxyquire
позволяет нам вводить наш собственный заглушка вместо внешней зависимости, в данном случае метод ping
который мы тестировали ранее. Затем мы можем использовать sinon
чтобы шпионить за sinon
методами заглушки и использовать sinon-stub-promise
чтобы позволить нам returnsPromise
. Это обещание может быть разрешено или отклонено, как мы желаем в тесте, чтобы проверить ответ обертки на это.
import {expect} from 'chai';
import sinon from 'sinon';
import proxyquire from 'proxyquire';
let pingStub = {
ping: () => {}
};
let pingWrapper = proxyquire('../src/pingWrapper', {
'./ping': pingStub
});
describe('pingWrapper', () => {
let pingSpy;
const response = 'some response';
beforeEach(() => {
pingSpy = sinon.stub(pingStub, 'ping').returnsPromise();
pingSpy.resolves(response);
pingWrapper();
});
afterEach(() => {
pingStub.wrapResponse.restore();
});
it('wraps the ping', () => {
expect(pingSpy).to.have.been.calledWith(response);
});
});