Jasmine este cel mai popular biblioteca JS pentru unitatea de testare aplicații web. În acest tutorial, conceput pentru începători, vă vom prezenta un ghid rapid și complet pentru testarea cu Jasmine.
veți fi prezentat Jasmine, un cadru popular de testare bazat pe comportament pentru JavaScript. Vom vedea, de asemenea, un exemplu practic simplu despre cum să scrieți teste unitare cu Jasmine, care vă pot ajuta să verificați cu ușurință erorile din codul dvs.
pe scurt, vom vedea cum să scrieți suitele de testare, specificațiile și așteptările și cum să aplicați Jasmine matchers încorporate sau să vă construiți propriile matchers personalizate
vom vedea, de asemenea, cum puteți grupa suitele de dragul organizării testelor pentru baze de cod mai complexe.
introducerea Jasmine
Jasmine este un foarte popular JavaScript de dezvoltare bazate pe comportament (în BDD, scrie teste înainte de a scrie cod real) cadru pentru unitatea de testare aplicații JavaScript. Oferă utilități care pot fi utilizate pentru a rula teste automate atât pentru codul sincron, cât și pentru cel asincron.
Jasmine are multe caracteristici, cum ar fi:
- Este rapid și are aeriene reduse și nu dependențe externe.
- este o bibliotecă inclusă în baterii și oferă tot ce aveți nevoie pentru testarea codului.
- este disponibil atât pentru nod și browser-ul.
- acesta poate fi utilizat cu alte limbi, cum ar fi Python și Ruby.
- nu necesită DOM.
- oferă o sintaxă curată și ușor de înțeles și, de asemenea, un API bogat și simplu.
- putem folosi limbajul natural pentru a descrie testele și rezultatele așteptate.Jasmine este un instrument open source care este disponibil sub licența permisivă MIT. Începând cu această scriere, cea mai recentă versiune majoră este Jasmine 3.0, care oferă noi caracteristici și unele modificări de rupere. Versiunea 2.99 a Jasmine va oferi diferite avertismente de depreciere pentru apartamentele care au un comportament diferit în versiunea 3.0, ceea ce va facilita migrarea dezvoltatorilor la noua versiune.
puteți citi despre noile caracteristici și modificările de rupere din acest document.
utilizarea Jasmine
puteți utiliza Jasmine în mai multe moduri diferite:
- În vechiul mod prin includerea atât a miezului Jasmine, cât și a fișierelor dvs. de testare folosind un
<scri
pt> etichetă, - ca instrument CLI folosind nod.js,
- ca o bibliotecă în nod.js,
- ca parte a unui sistem de construcție ca Gulp.js sau Grunt.js via grunt-contrib-jasmine și gulp-Jasmine-browser
de asemenea, puteți utiliza Jasmine pentru testarea codului Python cu jasmine-py care poate fi instalat de la PyPI folosind comanda
pip install jasmine
. Acest pachet conține atât un server web care servește și execută o suită Jasmine pentru proiectul dvs., cât și un script CLI pentru rularea testelor și integrărilor continue.Jasmine este de asemenea disponibil pentru proiecte Ruby prin jasmine-gem, care poate fi instalat prin adăugarea
gem 'jasmine'
la Gemfile și ruleazăbundle install
. Acesta include un server pentru servirea și rularea testelor, un script CLI și, de asemenea, generatoare pentru proiectele Ruby on Rails.acum să ne concentrăm asupra modului de utilizare a Jasmine cu JavaScript:
utilizarea Standalone Jasmine
începeți prin a descărca cea mai recentă versiune de Jasmine de pe pagina lansări.
apoi pur și simplu extrageți fișierul zip, de preferință într-un folder din proiectul pe care doriți să îl testați.
folderul va conține o grămadă de fișiere și foldere implicite:
/src
: conține fișierele sursă pe care doriți să le testați. Aceasta poate fi ștearsă fie dacă aveți deja configurarea folderului proiectului dvs., fie poate fi utilizată și atunci când este cazul pentru găzduirea codului sursă./lib
: conține fișierele de bază Jasmine./spec
: conține testele pe care urmează să le scrieți.SpecRunner.html
: acest fișier este folosit ca un alergător de testare. Executați specificațiile prin simpla lansare a acestui fișier.acesta este conținutul unui fișier implicit
SpecRunner.html
:<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>Jasmine Spec Runner v3.2.1</title> <link rel="shortcut icon" type="image/png" href="lib/jasmine-3.2.1/jasmine_favicon.png"> <link rel="stylesheet" href="lib/jasmine-3.2.1/jasmine.css"> <script src="lib/jasmine-3.2.1/jasmine.js"></script> <script src="lib/jasmine-3.2.1/jasmine-html.js"></script> <script src="lib/jasmine-3.2.1/boot.js"></script> <!-- include source files here... --> <script src="src/Player.js"></script> <script src="src/Song.js"></script> <!-- include spec files here... --> <script src="spec/SpecHelper.js"></script> <script src="spec/PlayerSpec.js"></script></head><body></body></html>
rețineți că trebuie să modificați fișierele incluse din folderele
/src
și/spec
pentru a conține sursa reală și fișierele de testare.utilizarea Jasmine ca o bibliotecă
puteți utiliza, de asemenea, Jasmine ca o bibliotecă în proiectul dumneavoastră. De exemplu, următorul cod importă și execută Jasmine:
var Jasmine = require('jasmine');var jasmine = new Jasmine();jasmine.loadConfigFile('spec/support/jasmine.json');jasmine.execute();
Mai întâi solicităm/importăm Jasmine și folosim metoda
loadConfigFile()
pentru a încărca fișierul de configurare disponibil de laspec/support/jasmine.json
apoi în cele din urmă executăm Jasmine.utilizarea Jasmine prin CLI
puteți utiliza, de asemenea, Jasmine din CLI, care vă permite să rulați cu ușurință teste Jasmine și implicit de ieșire rezultatele în terminal.
vom urma această abordare pentru a rula testele noastre de exemplu în acest ghid, deci mai întâi mergeți mai departe și executați următoarea comandă pentru a instala Jasmine la nivel global:
npm install -g jasmine
poate fi necesar să rulați sudo pentru instalarea pachetelor NPM la nivel global, în funcție de configurația npm.
acum, creați un folder pentru proiectul dvs. și navigați în interiorul acestuia:
$ mkdir jasmine-project $ cd jasmine-project
apoi, executați următoarea comandă pentru a inițializa proiectul pentru Jasmine:
această comandă creează pur și simplu un folder spec și un fișier de configurare JSON. Aceasta este ieșirea
dir
comandă:.└── spec └── support └── jasmine.json2 directories, 1 file
acesta este conținutul unui implicit
jasmine.json
fișier:{ "spec_dir": "spec", "spec_files": pec.js" ], "helpers": , "stopSpecOnExpectationFailure": false, "random": true}
-
spec_dir
: specifică unde Jasmine caută fișiere de testare. spec_files
: specifică modelele fișierelor de testare, în mod implicit toate fișierele JS care se termină cu șiruri Spec sau spec.helpers
: specifică unde Jasmine caută fișiere helper. Fișierele Helper sunt executate înainte de specificații și pot fi folosite pentru a defini matchers personalizate.stopSpecOnExpectationFailure
: când este setat la true se va opri imediat o spec pe primul eșec al unei așteptări (poate fi folosit ca opțiune CLI prin--stop-on-failure
).-
random
: când este setat la True Jasmine va rula pseudo-aleatoriu cazurile de testare (poate fi folosit ca opțiune CLI prin--random
).
spec_files
șihelpers
Matricele pot conține, de asemenea, modele Glob (datorită pachetului node-glob) pentru specificarea căilor de fișiere pe care le utilizați de obicei pentru a specifica un set de fișiere atunci când lucrați în Bash (de exemplu,ls *.js
).dacă nu utilizați locația implicită pentru fișierul de configurare
jasmine.json
, trebuie doar să specificați locația personalizată prin opțiuneajasmine --config
.puteți găsi mai multe opțiuni CLI din documentele oficiale.
înțelegerea Jasmine
În această secțiune vom învăța despre elementele de bază ale Jasmine de testare, cum ar fi apartamente, specificatii, așteptările, matchers și spioni, etc.
în folderul proiectului, executați următoarea comandă pentru a inițializa un nou modul nod:
aceasta va crea un fișier
package.json
cu informații implicite:{ "name": "jasmine-project", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": , "author": "", "license": "ISC"}
apoi, creați un fișier
index.js
și adăugați următorul cod:function fibonacci(n){ if (n === 1) { return ; } else { var s = fibonacci(n - 1); s.push(s + s); return s; }}function isPrime(num){ for (let i = 2; i < num; i++) if (num % i === 0) return false; return num !== 1 && num !== 0;}function isEven(n) { return n % 2 == 0;}function isOdd(n) { return Math.abs(n % 2) == 1;}function toLowerCase(str){ return str.toLowerCase();}function toUpperCase(str){ return str.toUpperCase();}function contains(str, substring, fromIndex){ return str.indexOf(substring, fromIndex) !== -1;}function repeat(str, n){ return (new Array(n + 1)).join(str);}module.exports = { fibonacci: fibonacci, isPrime: isPrime, isEven: isEven, isOdd: isOdd, toLowerCase: toLowerCase, toUpperCase: toUpperCase, contains: contains, repeat: repeat};
Suites
o suită grupează un set de specificații sau cazuri de testare. Este folosit pentru a testa un comportament specific al codului JavaScript care este de obicei încapsulat de un obiect/clasă sau o funcție. Este creat folosind funcția Jasmine global
describe()
care are doi parametri, titlul suitei de testare și o funcție care implementează codul real al suitei de testare.să începem prin crearea primei noastre suite de testare. În folderul
spec
creați un fișierMyJSUtilitiesSpec.js
și adăugați:describe("MyJSUtilities", function() { /* ... */ });
MyJSUtilities este numele acestei suite de testare de nivel superior.
cum se grupează și se cuibăresc suitele
pentru o mai bună organizare și descriere exactă a setului nostru de teste, putem cuibări suitele în interiorul suitei de nivel superior. De exemplu, să adăugăm două suite la suita MyJSUtilities:
describe("String Utils", function() { /*...*/});describe("Math Utils", function() { /*...*/});
în interiorul suitei Math Utils, să adăugăm și două suite imbricate:
describe("Basic Math Utils", function() { /* ... */ }); describe("Advanced Math Utils", function() { /* ... */ });
grupăm testele aferente în teste pentru Utils String, Utils Math Basic și Utils Math Advanced și le cuibărim în interiorul testului de nivel superior suite myjsutilities. Aceasta va compune specificațiile dvs. ca arbori similari cu o structură de foldere.
structura de cuibărit va fi afișată în raport, ceea ce vă face ușor să găsiți teste nereușite.
cum se exclud suitele
puteți dezactiva temporar o suită utilizând funcția
xdescribe()
. Are aceeași semnătură (parametri) ca odescribe()
funcție ceea ce înseamnă că puteți dezactiva rapid suitele existente adăugând pur și simplu unx
la funcție.specificațiile dintr-o funcțiexdescribe()
vor fi marcate în așteptare și nu vor fi executate în raport.Specificații
o spec declară un caz de testare care aparține unei suite de testare. Acest lucru se face apelând funcția globală Jasmine
it()
care ia doi parametri, titlul spec (care descrie logica pe care dorim să o testăm) și o funcție care implementează cazul de testare real.o specificație poate conține una sau mai multe așteptări. Fiecare așteptare este pur și simplu o afirmație care poate returna fie
true
saufalse
. Pentru ca spec să fie trecut, toate așteptările aparținând spec trebuie să fietrue
altfel spec eșuează.în suita noastră String Utils, adăugați aceste specificații:
describe("String Utils", function() { it("should be able to lower case a string",function() { /*...*/ }); it("should be able to upper case a string",function() { /*...*/ }); it("should be able to confirm if a string contains a substring",function() { /*...*/ }); it("should be able repeat a string multiple times",function() { /*...*/ });});
în suita noastră Basic Math Utils să adăugăm câteva specificații:
describe("Basic Math Utils", function() { it("should be able to tell if a number is even",function() { /*...*/ }); it("should be able to tell if a number is odd",function() { /*...*/ }); });
pentru Utils Math avansate, să adăugăm specificațiile:
describe("Advanced Math Utils", function() { it("should be able to tell if a number is prime",function() { /*...*/ }); it("should be able to calculate the fibonacci of a number",function() { /*...*/ }); });
cum se exclud specificațiile
la fel ca suitele, puteți exclude și specificațiile individuale folosind
xit()
funcție care dezactivează temporarit()
și marchează specificațiile ca fiind în așteptare.așteptările
așteptările sunt create folosind
expect()
funcție care ia o valoare numită real (aceasta poate fi valori, expresii, variabile, funcții sau obiecte etc.). Așteptările compun specificațiile și sunt utilizate împreună cu funcțiile matcher (prin înlănțuire) pentru a defini ce așteaptă dezvoltatorul de la o anumită unitate de cod pentru a efectua.o funcție matcher compară între o valoare reală (transmisă la
expect()
funcția cu care este înlănțuită) și o valoare așteptată (transmisă direct ca parametru către matcher) și returnează fie adevărat, fie fals, care fie trece, fie eșuează spec.puteți înlănțui
expect()
funcția cu mai multe matchere. Pentru a anula / inversa rezultatul boolean al oricărui matcher, puteți utilizanot
cuvânt cheie înainte de a apela matcher.să implementăm specificațiile exemplului nostru. Pentru moment vom folosi vom folosi
expect()
cunothing()
matcher care face parte din matchers built-in pe care le vom vedea un pic mai târziu. Acest lucru va trece toate specificațiile, deoarece nu ne așteptăm la nimic în acest moment.describe("MyJSUtilities", function() {describe(">String Utils", function() { it("should be able to lower case a string",function() { expect().nothing(); }); it("should be able to upper case a string",function() { expect().nothing(); }); it("should be able to confirm if a string contains a substring",function() { expect().nothing(); }); it("should be able repeat a string multiple times",function() { expect().nothing(); }); });describe("Math Utils", function() { describe("Basic Math Utils", function() { it("should be able to tell if a number is even",function() { expect().nothing(); }); it("should be able to tell if a number is odd",function() { expect().nothing(); }); }); describe("Advanced Math Utils", function() { it("should be able to tell if a number is prime",function() { expect().nothing(); }); it("should be able to calculate the fibonacci of a number",function() { expect().nothing(); }); }); });});
aceasta este o captură de ecran a rezultatelor în acest moment:
avem opt specificații trecute și zero eșecuri.
puteți utiliza fie matchers built-in sau, de asemenea, crea propriile matchers personalizate pentru nevoile dvs. specifice.
built-in Matchers
Jasmine oferă un set bogat de matchers built-in. Să vedem câteva dintre cele importante:
-
toBe()
pentru testarea identității, -
toBeNull()
pentru testareanull
, -
toBeUndefined()/toBeDefined()
pentru testare pentruundefined
/notundefined
, -
toBeNaN()
pentru testarea pentru Nan (nu un număr) -
toEqual()
pentru testarea pentru egalitate, -
toBeFalsy()/toBeTruthy()
pentru testarea falsității/veridicității etc.
puteți găsi lista completă a matchers din docs.
să pună în aplicare acum specificatiile noastre cu unele dintre aceste matchers atunci când este cazul. Mai întâi importăm funcțiile pe care le testăm în
MyJSUtilitiesSpec.js
fișier:const utils = require("../index.js");
apoi, începeți cu șirul Utils suite și schimbați
expect().nothing()
cu așteptările corespunzătoare.de exemplu pentru prima spec, ne așteptăm ca metoda
toLowerCase()
să fie definită mai întâi și, în al doilea rând, să returneze un șir cu litere mici, adică:it("should be able to lower case a string",function() { expect(utils.toLowerCase).toBeDefined(); expect(utils.toLowerCase("HELLO WORLD")).toEqual("hello world"); });
acesta este codul complet pentru suită:
describe(">String Utils", function() { it("should be able to lower case a string",function() { expect(utils.toLowerCase).toBeDefined(); expect(utils.toLowerCase("HELLO WORLD")).toEqual("hello world"); }); it("should be able to upper case a string",function() { expect(utils.toUpperCase).toBeDefined(); expect(utils.toUpperCase("hello world")).toEqual("HELLO WORLD"); }); it("should be able to confirm if a string contains a substring",function() { expect(utils.contains).toBeDefined(); expect(utils.contains("hello world","hello",0)).toBeTruthy(); }); it("should be able repeat a string multiple times",function() { expect(utils.repeat).toBeDefined(); expect(utils.repeat("hello", 3)).toEqual("hellohellohello"); }); });
Matchers personalizate
Jasmine oferă posibilitatea de a scrie matchers personalizate pentru punerea în aplicare afirmații care nu sunt acoperite de matchers built-in sau doar de dragul de a face teste mai descriptiv și ușor de citit.
de exemplu, să luăm următoarele specificații:
it("should be able to tell if a number is even",function() { expect(utils.isEven).toBeDefined(); expect(utils.isEven(2)).toBeTruthy(); expect(utils.isEven(1)).toBeFalsy(); });
Să presupunem că metoda
isEven()
nu este implementată. Dacă rulăm testele, vom primi mesaje precum următoarea captură de ecran:mesajul de eșec pe care îl primim spune că se așteaptă ca nedefinit să fie definit, ceea ce nu ne oferă nicio idee despre ce se întâmplă. Deci, să facem acest mesaj mai semnificativ în contextul domeniului nostru de cod (acest lucru va fi mai util pentru bazele de cod complexe). Pentru această chestiune, să creăm un matcher personalizat.
vom crea matchers personalizate folosind
addMatchers()
metoda care ia un obiect compus din una sau mai multe proprietăți care vor fi adăugate ca matchers. Fiecare proprietate ar trebui să ofere o funcție din fabrică care să ia doi parametri:util
, care are un set de funcții de utilitate pe care să le folosească matcherii (vezi:matchersUtil.js
) șicustomEqualityTesters
care trebuie trecut în dacăutil.equals
este numit, și ar trebui să returneze un obiect cu uncompare
funcție care va fi apelat pentru a verifica așteptările.trebuie să înregistrăm matcherul personalizat înainte de a executa fiecare spec folosind metoda
beforeEach()
:describe("/Basic Math Utils", function () {beforeEach(function () {jasmine.addMatchers({hasEvenMethod: function (util, customEqualityTesters) {return {compare: function (actual, expected) {var result = { pass: utils.isEven !== undefined };if (result.pass) {result.message = "Expected isEven() to be not defined."}else {result.message = "Expected isEven() to be defined."}return result;}}}});});/*...*/});
putem folosi apoi matcherul personalizat în loc de
expect(utils.isEven).toBeDefined()
:expect().hasEvenMethod();
Acest lucru ne va oferi un mesaj de eșec mai bun:
folosind beforeEach() și afterEach()
pentru inițializarea și curățarea specificațiilor, Jasmine oferă două funcții globale,
beforeEach()
șiafterEach()
:- funcția
beforeEach
este apelată o dată înainte de fiecare spec în suita în care este apelată. - funcția
afterEach
este apelată o dată după fiecare spec în suita unde este apelată.
de exemplu, dacă trebuie să utilizați orice variabile din suita de testare, le puteți declara pur și simplu la începutul funcției
describe()
și puteți pune orice cod de inițializare sau instanțiere în interiorul unei funcțiibeforeEach()
. În cele din urmă, puteți utiliza funcțiaafterEach()
pentru a reseta variabilele după fiecare spec, astfel încât să puteți avea testarea unității pure fără a fi nevoie să repetați inițializarea și Codul de curățare pentru fiecare spec.funcția
beforeEach()
este, de asemenea, perfect combinată cu multe API-uri Jasmine, cum ar fi metodaaddMatchers()
pentru a crea matchers personalizate sau, de asemenea, cu funcțiadone()
pentru a aștepta operațiile asincrone înainte de a continua testarea.eșecul unui Test
puteți forța un test să eșueze folosind metoda globală
fail()
disponibilă în Jasmine. De exemplu:it("should explicitly fail", function () { fail('Forced to fail'); });
ar trebui să primiți următoarea eroare:
testarea excepțiilor
când vă testați codul, erorile și excepțiile pot fi aruncate, deci ar putea fi necesar să testați pentru aceste scenarii. Jasmine oferă
toThrow()
șitoThrowError()
matchers pentru a testa atunci când o excepție este aruncat sau pentru a testa pentru o excepție specifică, respectiv.de exemplu, dacă avem o funcție care aruncă o
TypeError
excepție:function throwsError() { throw new TypeError("A type error"); }
ai putea scrie un spec care să testeze pentru dacă o excepție este aruncat:
it('it should throw an exception', function () { expect(throwsError).toThrow(); });
sau ai putea folosi, de asemenea, testul pentru specific
TypeError
excepție:it('it should throw a TypeError', function () { expect(throwsError).toThrowError(TypeError); });
înțelegerea spionilor
cel mai adesea, metodele depind de alte metode. Aceasta înseamnă că atunci când testați o metodă, puteți ajunge, de asemenea, să testați dependențele acesteia. Acest lucru nu este recomandat în testare, adică trebuie să vă asigurați că testați funcția pură izolând metoda și văzând cum se comportă având în vedere un set de intrări.
Jasmine oferă spioni care pot fi folosiți pentru a spiona / asculta apeluri de metode pe obiecte și pentru a raporta dacă se apelează o metodă și cu ce context și argumente.
Jasmine oferă două moduri de spionaj pe apeluri metoda: folosind
spyOn()
saucreateSpy()
metode.puteți utiliza
spyOn()
când metoda există deja pe obiect, altfel trebuie să utilizațijasmine.createSpy()
care returnează o nouă funcție.în mod implicit, un spion va raporta numai dacă un apel a fost efectuat fără a apela prin funcția spied (i.e funcția se va opri de executare), dar puteți schimba comportamentul implicit folosind aceste metode:
-
and.callThrough()
: apel prin funcția originală, -
and.returnValue(value)
: returnați valoarea specificată, -
and.callFake(fn)
: apelați funcția fals în loc de cel original, -
and.throwError(err)
: arunca o eroare, -
and.stub()
: resetează comportamentul stubbing implicit.
puteți utiliza un spion pentru a aduna statistici run-time pe funcția spied, de exemplu, dacă doriți să știți cât de multe ori funcția a fost numit.
spunem că vrem să ne asigurăm că
toUpperCase()
metoda folosește metoda încorporatăString.toUpperCase()
, trebuie să spionăm pur și simpluString.toUpperCase()
folosind:it("should be able to upper case a string", function () {
var spytoUpperCase = spyOn(String.prototype, 'toUpperCase')
expect(utils.toUpperCase).toBeDefined(); expect(utils.toUpperCase("hello world")).toEqual("HELLO WORLD"); expect(String.prototype.toUpperCase).toHaveBeenCalled(); expect(spytoUpperCase.calls.count()).toEqual(1); });
testul a eșuat din cauza celei de-a doua așteptări, deoarece
utils.toUpperCase("hello world")
a revenit nedefinit în locul lumii așteptate. Asta pentru că, așa cum am menționat, mai devreme după crearea spionului petoUpperCase()
, metoda nu este executată. Trebuie să schimbăm acest comportament implicit apelândcallThrough()
:vă rugăm să rețineți că o
spy
funcția înlocuiește funcția spionat cu un ciot în mod implicit. Dacă trebuie să apelați funcția originală în schimb, puteți adăuga.and.callThrough()
laspy
obiect.var spytoUpperCase = spyOn(String.prototype, 'toUpperCase').and.callThrough();
acum toate așteptările trec.
de asemenea, puteți utiliza
and.callFake()
sauand.returnValue()
pentru a falsifica fie spionat pe funcția sau doar valoarea returnată, dacă nu pentru a apela prin funcția reală:var spytoUpperCase = spyOn(String.prototype, 'toUpperCase').and.returnValue("HELLO WORLD");
var spytoUpperCase = spyOn(String.prototype, 'toUpperCase').and.callFake(function(){ return "HELLO WORLD"; });
acum, dacă vom ajunge să nu folosim construit în
String.toUpperCase()
în propria noastrăutils.toUpperCase()
punerea în aplicare, vom obține aceste eșecuri:cele două așteptări
expect(String.prototype.toUpperCase).toHaveBeenCalled()
expect(spytoUpperCase.calls.count()).toEqual(1)
au eșuat.cum se tratează Asincronitatea în Jasmine
dacă codul pe care îl testați conține operații asincrone, aveți nevoie de o modalitate de a anunța Jasmine când s-au finalizat operațiile asincrone.
în mod implicit, Jasmine așteaptă ca orice operație asincronă, definită printr-un apel invers, promisiune sau cuvântul cheie
async
să fie terminată. Dacă Jasmine găsește un cuvânt cheie callback, promise sau async într-una din aceste funcții:beforeEach
afterEach
beforeAll
afterAll
șiit
va aștepta ca asincronul să fie făcut înainte de a trece la următoarea operație.folosind done() cu beforeEach () / it() ..
să luăm exemplul nostru
simulateAsyncOp()
care simulează o operație asincronă folosindsetTimeout()
. Într-un scenariu din lumea reală, aceasta poate fi o cerere Ajax sau orice lucru similar care se întâmplă asincron:function simulateAsyncOp(callback){
setTimeout(function () { callback(); }, 2000); }
pentru a testa această funcție putem folosi
beforeEach()
funcția cudone()
apel invers. Codul nostru trebuie să invocedone()
pentru a-i spune lui Jasmine că operația asincronă s-a încheiat:describe("/Async Op", function () {var asyncOpCompleted = false;beforeEach(function (done) {utils.simulateAsyncOp(function(){ asyncOpCompleted = true; done();});});it("should be able to tell if the async call has completed", function () { expect(asyncOpCompleted).toEqual(true);});});
putem observa rapid un dezavantaj al acestei metode, deci trebuie să scriem codul nostru pentru a accepta
done()
apel invers. În cazul nostru, nu am codificat metodadone()
însimulateAsyncOp(fn)
dar am furnizat un parametru de apel invers doar pentru a putea apeladone()
.utilizarea promisiunilor
dacă nu doriți să creați un cod care depinde de modul în care scrieți testul, puteți utiliza în schimb o promisiune și puteți apela
done()
apel invers atunci când promisiunea s-a rezolvat. Sau mai bine, în Jasmine 2.7+ , dacă codul dvs. returnează unPromise
, Jasmine va aștepta până când este rezolvat sau respins înainte de a executa următorul cod.folosind asincron/wait
Jasmine 2.7+ acceptă
async
șiawait
solicită specificații. Acest lucru vă scutește de la punerea afirmă într-un.then()
sau.catch()
bloc.it("should work with async/await", async () => { let completed = false; completed = await utils.simulateAsyncOp(); expect(completed).toEqual(true); });
aceasta este implementarea
simulateAsyncOp
:function simulateAsyncOp() {
return new Promise(resolve => { setTimeout(() => { resolve(true); }, 1000); }); }
folosind Jasmine Clock
ceasul Jasmine este folosit pentru a testa codul asincron care depinde de funcții de timp, cum ar fi
setTimeout()
în același mod în care testăm codul sincron prin batjocorirea API-urilor bazate pe timp cu metode personalizate. În acest fel, puteți executa funcțiile testate sincron controlând sau avansând manual ceasul.puteți instala ceasul Jasmine apelând funcția
jasmine.clock().install
în specificațiile sau suita dvs.după utilizarea ceasului, trebuie să îl dezinstalați pentru a restabili funcțiile originale.
cu Jasmine clock, puteți controla JavaScript
setTimeout
sausetInterval
funcții bifând ceasul pentru a avansa în timp folosindjasmine.clock().tick
funcție, care ia numărul de milisecunde cu care vă puteți deplasa.de asemenea, puteți utiliza ceasul Jasmine pentru a bate joc de data curentă.
beforeEach(function () {jasmine.clock().install();});afterEach(function() {jasmine.clock().uninstall();});it("should call the asynchronous operation synchronously", function() {var completed = false;utils.simulateAsyncOp(function(){completed = true;});expect(completed).toEqual(false);jasmine.clock().tick(1001);expect(completed).toEqual(true);});
aceasta este
simulateAsyncOp
funcția:function simulateAsyncOp(callback){
setTimeout(function () { callback(); }, 1000); }
în cazul în care nu ați specificat un timp pentru funcția
mockDate
, aceasta va utiliza data curentă.erori de manipulare
dacă codul dvs. asincron eșuează din cauza unei erori, doriți ca specificațiile dvs. să eșueze corect. Începând cu Jasmine 2.6 + orice erori netratate sunt trimise la spec executat în prezent.
Jasmine oferă, de asemenea, o modalitate de a utiliza în cazul în care aveți nevoie pentru a eșua în mod explicit specificatiile:
- folosind
done()
apel invers cubeforeEach()
apelânddone.fail(err)
metodă, - pur și simplu trecând o eroare la
done(err)
apel invers (Jasmine 3+), - apelând
reject()
metoda unuiPromise
.
concluzie
În acest ghid am introdus Jasmine și am văzut cum să începeți să utilizați Jasmine pentru a testa unitatea codului JavaScript. Vă mulțumim pentru lectură!
Acest articol a fost publicat inițial în techiediaries.
- În vechiul mod prin includerea atât a miezului Jasmine, cât și a fișierelor dvs. de testare folosind un