Zoeken…
Basis bewering
Op het meest basale niveau biedt Unit Testing in elke taal beweringen tegen bekende of verwachte resultaten.
function assert( outcome, description ) {
var passFail = outcome ? 'pass' : 'fail';
console.log(passFail, ': ', description);
return outcome;
};
De populaire assertiemethode hierboven laat ons een snelle en eenvoudige manier zien om een waarde te bevestigen in de meeste webbrowsers en -interpreters zoals Node.js met vrijwel elke versie van ECMAScript.
Een goede eenheidstest is ontworpen om een discrete eenheid code te testen; meestal een functie.
function add(num1, num2) {
return num1 + num2;
}
var result = add(5, 20);
assert( result == 24, 'add(5, 20) should return 25...');
In het bovenstaande voorbeeld is de retourwaarde van de functie add(x, y)
of 5 + 20
duidelijk 25
, dus onze bewering van 24
moet mislukken en de assert-methode registreert een "fail" -regel.
Als we eenvoudigweg onze verwachte uitkomst van de bewering wijzigen, zal de test slagen en zou de resulterende output er ongeveer zo uitzien.
assert( result == 25, 'add(5, 20) should return 25...');
console output:
> pass: should return 25...
Deze eenvoudige bewering kan ervoor zorgen dat in veel verschillende gevallen uw "toevoegen" -functie altijd het verwachte resultaat oplevert en geen extra frameworks of bibliotheken vereist om te werken.
Een meer rigoureuze set beweringen zou er zo uitzien (met var result = add(x,y)
voor elke bewering):
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...');
En console-uitvoer zou dit zijn:
> pass: should return 0...
> pass: should return -1...
> pass: should return 1...
We kunnen nu veilig zeggen dat add(x,y)
... de som van twee gehele getallen moet retourneren . We kunnen deze samenvatten in zoiets als dit:
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;
}
}
Beloftestests met Mocha, Sinon, Chai en Proxyquire
Hier moeten we een eenvoudige klasse testen die een Promise
retourneert op basis van de resultaten van een externe ResponseProcessor
die tijd kost om uit te voeren.
Voor simplicty gaan we ervan uit dat de processResponse
methode zal nooit falen.
import {processResponse} from '../utils/response_processor';
const ping = () => {
return new Promise((resolve, _reject) => {
const response = processResponse(data);
resolve(response);
});
}
module.exports = ping;
Om dit te testen kunnen we de volgende tools gebruiken.
Ik gebruik het volgende test
in mijn package.json
bestand.
"test": "NODE_ENV=test mocha --compilers js:babel-core/register --require ./test/unit/test_helper.js --recursive test/**/*_spec.js"
Hiermee kan ik de syntaxis van es6
gebruiken. Het verwijst naar een test_helper
die eruit zal zien
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
kunnen we onze eigen stub injecteren in plaats van de externe ResponseProcessor
. We kunnen dan sinon
om de methoden van die stomp te bespioneren. We gebruiken de uitbreidingen van chai
dat chai-as-promised
injecteert om te controleren of de ping()
belofte methode wordt fullfilled
, en dat zij eventually
het verwachte antwoord terug.
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);
})
});
Laten we nu in plaats daarvan aannemen dat u iets wilt testen dat de reactie van ping
.
import {ping} from './ping';
const pingWrapper = () => {
ping.then((response) => {
// do something with the response
});
}
module.exports = pingWrapper;
Om de pingWrapper
te testen, pingWrapper
we gebruik van
Zoals eerder, laat Proxyquire
ons toe onze eigen stub te injecteren in de plaats van de externe afhankelijkheid, in dit geval de ping
methode die we eerder hebben getest. We kunnen dan sinon
om de methoden van die stomp te bespioneren en sinon-stub-promise
gebruiken om ons in returnsPromise
te stellen om terug te returnsPromise
. Deze belofte kan vervolgens worden opgelost of afgewezen zoals we in de test wensen, om de reactie van de verpakking daarop te testen.
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);
});
});