Suche…


Grundsätzliche Behauptung

Auf der untersten Ebene bietet Unit Testing in einer beliebigen Sprache Aussagen gegen bekannte oder erwartete Ergebnisse.

function assert( outcome, description ) { 
    var passFail = outcome ? 'pass' : 'fail'; 
    console.log(passFail, ': ', description);
    return outcome;
};

Die oben genannte beliebte Assertionsmethode zeigt uns eine schnelle und einfache Möglichkeit, einen Wert in den meisten Webbrowsern und Interpreters wie Node.js mit praktisch jeder Version von ECMAScript zu bestätigen.

Ein guter Unit-Test dient zum Testen einer diskreten Code-Einheit. normalerweise eine Funktion.

function add(num1, num2) { 
    return num1 + num2; 
} 
 
var result = add(5, 20); 
assert( result == 24, 'add(5, 20) should return 25...'); 

Im obigen Beispiel ist der Rückgabewert der Funktion add(x, y) oder 5 + 20 eindeutig 25 , daher sollte unsere Zusicherung von 24 fehlschlagen, und die Assert-Methode protokolliert eine "Fail" -Zeile.

Wenn wir einfach unser erwartetes Assertionsergebnis ändern, wird der Test erfolgreich sein und die resultierende Ausgabe würde ungefähr so ​​aussehen.

assert( result == 25, 'add(5, 20) should return 25...');

console output:

> pass: should return 25...

Diese einfache Behauptung kann sicherstellen, dass Ihre Funktion "Hinzufügen" in vielen verschiedenen Fällen immer das erwartete Ergebnis zurückgibt und keine zusätzlichen Frameworks oder Bibliotheken erfordert.

Ein strengerer Satz von Zusicherungen würde folgendermaßen aussehen (mit var result = add(x,y) für jede Zusicherung):

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

Und die Konsolenausgabe wäre folgendes:

> pass: should return 0...
> pass: should return -1...
> pass: should return 1...

Wir können nun mit Sicherheit sagen, dass add(x,y) … die Summe zweier Ganzzahlen ergibt . Wir können diese in so etwas aufrollen:

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-Testversprechen mit Mocha, Sinon, Chai und Proxyquire

Hier haben wir eine einfache zu testende Klasse, die ein Promise zurückgibt, basierend auf den Ergebnissen eines externen ResponseProcessor , dessen Ausführung Zeit erfordert.

Der Einfachheit halber gehen wir davon aus, dass die processResponse Methode niemals fehlschlagen wird.

import {processResponse} from '../utils/response_processor';

const ping = () => {
  return new Promise((resolve, _reject) => {
    const response = processResponse(data);
    resolve(response);
  });
}

module.exports = ping;

Um dies zu testen, können wir die folgenden Tools nutzen.

  1. mocha
  2. chai
  3. sinon
  4. proxyquire
  5. chai-as-promised

Ich verwende den folgenden test in meiner package.json Datei.

"test": "NODE_ENV=test mocha --compilers js:babel-core/register --require ./test/unit/test_helper.js  --recursive test/**/*_spec.js"

Dadurch kann ich die es6 Syntax verwenden. Es verweist auf einen test_helper , der aussehen wird

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 ermöglicht es uns, anstelle des externen ResponseProcessor eigenen Stub zu injizieren. Wir können dann mit sinon die Methoden dieses Stubs ausspionieren. Wir verwenden die Erweiterungen chai , dass chai-as-promised einspritzt zu überprüfen, ob die ping() Methode Versprechen ist fullfilled , und dass es eventually liefert die erforderliche Antwort.

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

Nehmen wir stattdessen an, Sie möchten etwas testen, das die Antwort von ping .

import {ping} from './ping';

const pingWrapper = () => {
  ping.then((response) => {
    // do something with the response
  });
}

module.exports = pingWrapper;

Um den pingWrapper zu testen, pingWrapper wir ihn

  1. sinon
  2. proxyquire
  3. sinon-stub-promise

Nach wie vor erlaubt Proxyquire , Proxyquire der externen Abhängigkeit einen eigenen Stub zu injizieren, in diesem Fall die zuvor getestete ping Methode. Wir können dann sinon um die Methoden dieses Stubs auszuspionieren und das sinon-stub-promise zu nutzen, um uns die returnsPromise sinon-stub-promise zu ermöglichen. Dieses Versprechen kann dann wie gewünscht im Test gelöst oder abgelehnt werden, um die Antwort des Wrappers darauf zu 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);
  });
});


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow