2015-06-06 10 views
6

ho una sezione di codice che utilizza node-sync in questo modo:Testing codice sincrono

function funcA() { 
    return new Promise(function(resolve, reject) { 
    Sync(function() { 
     return funcB.sync(); 
    }, function (err, result) { 
     if(err) { 
     reject(err); 
     } else { 
     resolve(result); 
     } 
    }); 
} 

Questo codice viene testato con moka + chai:

it("should return array", function() { 
    return funcA().then(function(result) { 
    expect(result).to.be.an.instanceof(Array); 
    }); 
}); 

Ha funzionato paio bene di mesi fa , ma ora questo test sempre timeout:

Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

quello che ho provato finora:

  • utilizzando done() invece di restituire una promessa
  • sostituzione node-sync con synchronize.js
  • aumentando timeout

Quello che ho scoperto, è che expect(... parte di questo test è, infatti, essere chiamato , ma solo dopo che la moka ha ucciso il test. Indipendentemente dall'intervallo di timeout attualmente impostato, expect(.. viene chiamato sempre ~ 20 millisecondi dopo che ho ricevuto il messaggio Error: timeout.

Ho risolto il problema aggiungendo setInterval(function(){}, 10) nella parte superiore del file di test. Mi piacerebbe sapere perché questo ha funzionato e se c'è un modo migliore per risolvere questo?

[MODIFICA] Sembra che questo sia un problema specifico della versione del nodo. Il test fallisce su 0.12.4 ma funziona correttamente su 0.10.38.

[EDIT] Il codice attuale è disponibile here.

+1

Sembra molto strano .. Posso riprodurlo ma non riesco a capire quale sia il problema. potrebbe essere una soluzione lunga, ma forse scavare nella sincronizzazione dei nodi, vedere questi biglietti github [qui] (https://github.com/ybogdanov/node-sync/issues/41) e [qui] (https: // github. it/ybogdanov/node-sync/issues/36) –

+0

btw è tipicamente consigliabile (imho) non eseguire il codice in modo asincrono in un test. So che stai tentando di eseguire questo blocco di sincronizzazione, ma forse prova il modulo chai-come promesso in modo da poter rimuovere il 'done' –

risposta

1

Si può solo mancare il done() callback:

it("should return array", function(done) { 
    funcA().then(function(result) { 
     expect(result).to.be.an.instanceof(Array); 
     done(); 
    }); 
}); 

http://mochajs.org/#asynchronous-code

+0

Ehi, grazie per il suggerimento - come menzionato in questione ho già provato' done() '. Inoltre, la restituzione di una promessa dovrebbe funzionare bene (in effetti è stato collegato alla stessa sezione in mocha docs in cui è descritto). Il mio problema sembra essere correlato alla versione del nodo. –

2

Sulla base della sua code, io parto dal presupposto che la funzione funcB è in esecuzione il codice in modo sincrono .

Così quando creo funcB in questo modo:

function funcB() { 
    return [1, 2, 3]; 
} 

ed eseguire il test, Mocha mostra un errore:

Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

Ma se converto il funcB in funzione asincrono come questo :

Mocha esegue il test senza alcun problema:

✓ should return an array


Quindi il mio codice completo che corre ok (il funcB commentato è quello che causerà l'errore) è questo:

// install dependencies 
// npm install promise 
// npm install sync 
var Promise = require('promise'); 
var assert = require('assert'); 
var Sync = require('sync'); 

function funcA() { 
    return new Promise(function (resolve, reject) { 
    Sync(function() { 
     return funcB.sync(); 
    }, function (err, result) { 
     if (err) { 
     reject(err); 
     } else { 
     resolve(result); 
     } 
    }); 
    }); 
} 

// function funcB() { 
// return [1, 2, 3]; 
// } 

function funcB(cb) { 
    process.nextTick(function() { 
    cb(null, [1, 2, 3]); 
    }); 
} 

it("should return an array", function(done) { 
    return funcA().then(
    function (result) { 
     console.log(result); 
     assert.equal(Array.isArray(result), true); 
     done(); 
    } 
); 
}); 

Così sto parere, credo che l'abuso di il sync method (utilizzandolo su funzioni sincrone) creato dalla libreria di sincronizzazione è quello che sta causando questo problema.

+0

Hey Wilson! Grazie per questo, ma è ancora un hack e non risponde perché questo accade. Immagino che il mio uso di 'setInterval' abbia lo stesso identico scopo del trucco' nextTick'. Sembra che il nodo si "addormenta" e debba essere riattivato da 'nextTick' o' setInterval'. La domanda è: perché questo accade e se si tratta di un nodo problema, problema di sincronizzazione o un comportamento previsto? Mi piacerebbe andare fino in fondo. –

+0

Forse ho sbagliato ma ragionando dal doc del [metodo] (https://github.com/ybogdanov/node-sync/blob/master/lib/sync.js#L27) che dice: * "sync() metodo semplicemente trasforma qualsiasi funzione asincrona in sincrona "* quindi chiamare questo metodo da una funzione di sincronizzazione come funcB, per me potrebbe essere potenzialmente la fonte del bug. – Wilson

1

È possibile utilizzare un parametro di timeout per l'eseguibile di mocha.

Ad esempio, se si desidera un timeout di 500 millisecondi, basta cambiare la tua package.json a:

"scripts": { 
    "test": "mocha specs --timeout 500 --require specs/helpers/chai.js" 
}, 

E forse la promessa viene respinta, quindi bisogna chiamare done utilizzando catch metodo.

it("should return array", function(done) { 
    return funcA().then(function(result) { 
     expect(result).to.be.an.instanceof(Array); 
     done(); 
    }).catch(done); 
}); 

Ciò consentirebbe anche di eseguire il debug di eventuali errori che potrebbero verificarsi nel codice di promessa.

+0

Ehi! Come menzionato nella domanda, ho provato ad aumentare il timeout - il test fallisce * sempre * subito dopo il timeout (indipendentemente dal valore di timeout). Avere la cattura è un buon consiglio, ma questo test non fallisce, va a finire. –

+0

@KonradDzwinel Hmm .. Sembra che tu stia provando a testare un codice con promesse che fanno tutto nello stesso processo. Prova a cambiare 'setTimeout()' in 'process.nextTick(); 'e controlla se funziona ancora.Inoltre, puoi inviare il codice del metodo che stai provando a testare? – Tulio

+0

Ehi! Tutto è disponibile [qui] (https://github.com/kdzwinel/Proofreader). I test passano sul nodo 0.10 ma falliscono su 0.12. Proverò a cambiare setInterval su nextTick più tardi. La mia ipotesi è che funzionerà - la domanda è: perché devo attivare manualmente il tick successivo nel nodo 0.12? –