Estoy usando mocha para probar una aplicación escrita para node.js
Me pregunto si es posible unir las funciones de prueba que no se han exportado en un módulo.
Ejemplo:
Tengo muchas funciones definidas así en foobar.js
function private_foobar1(){
...
}
function private_foobar2(){
...
}
y algunas funciones exportadas como públicas:
exports.public_foobar3 = function(){
...
}
El caso de prueba se estructura de la siguiente manera:
describe("private_foobar1", function() {
it("should do stuff", function(done) {
var stuff = foobar.private_foobar1(filter);
should(stuff).be.ok;
should(stuff).....
Obviamente esto no funciona, ya private_foobar1
que no se exporta.
¿Cuál es la forma correcta de probar los métodos privados? ¿Tiene mocha algunos métodos incorporados para hacerlo?
Respuestas:
Si el módulo no exporta la función, no se puede invocar mediante código de prueba fuera del módulo. Eso se debe a cómo funciona JavaScript, y Mocha no puede evitar esto por sí solo.
En los pocos casos en que determiné que probar una función privada es lo correcto, lo que hice fue establecer alguna variable de entorno que mi módulo verifica para determinar si se está ejecutando en una configuración de prueba o no. Si se ejecuta en la configuración de prueba, exporta funciones adicionales a las que puedo llamar durante la prueba.
La palabra "medio ambiente" se usa libremente aquí. Puede significar una comprobación
process.env
o algo más que pueda comunicarse con el módulo "estás siendo probado ahora". Las instancias donde tuve que hacer esto fueron en un entorno RequireJS, y lo he usadomodule.config
para este propósito.fuente
SyntaxError: 'import' and 'export' may only appear at the top level
import
,export
dentro de un bloque. Eventualmente podrá lograr este tipo de cosas en ES6 con el cargador del sistema. Una forma demodule.exports = process.env.NODE_ENV === 'production' ? require('prod.js') : require('dev.js')
evitarlo ahora es usar y almacenar sus diferencias de código es6 en esos archivos respectivos.Echa un vistazo al módulo de recableado . Le permite obtener (y manipular) variables y funciones privadas dentro de un módulo.
Entonces, en su caso, el uso sería algo como:
fuente
Cannot find module '../../package' from 'node.js'
. Alguien familiarizado con esto?.ts
,typescript
ejecuto usandots-node
@cluAquí hay un flujo de trabajo realmente bueno para probar sus métodos privados explicado por Philip Walton, un ingeniero de Google en su blog.
Principio
_
, por ejemplo,Luego use una tarea de compilación o su propio sistema de compilación (por ejemplo, grunt-strip-code) para eliminar este bloque para compilaciones de producción.
Sus compilaciones de prueba tienen acceso a su API privada, y sus compilaciones de producción no.
Retazo
Escribe tu código como este:
Y tus gruñidos como ese
Mas profundo
En un artículo posterior , explica el "por qué" de "probar métodos privados"
fuente
Si prefiere que sea simple, simplemente exporte los miembros privados también, pero claramente separados de la API pública con alguna convención, por ejemplo, prefije con
_
o anidelos bajo un solo objeto privado .fuente
Hice un paquete npm para este propósito que puede resultarle útil: require-from
Básicamente expones métodos no públicos mediante:
nota:
testExports
puede ser cualquier nombre válido que desee, excepto,exports
por supuesto.Y de otro módulo:
fuente
requireFrom
con los parámetros correctos). Además, si el módulo contextExports
es cargado por unarequire
llamada antes de cargarlorequireFrom
,requireFrom
regresaráundefined
. (Lo acabo de probar). Si bien a menudo es posible controlar el orden de carga de los módulos, no siempre es práctico. (Como lo demuestran algunas preguntas de Mocha sobre SO). Esta solución tampoco suele funcionar con módulos de tipo AMD. (Cargo módulos AMD en Node diariamente para realizar pruebas).He agregado una función adicional que denomino Internal () y devuelvo todas las funciones privadas desde allí. Esta función interna () se exporta. Ejemplo:
Puede llamar a las funciones internas de esta manera:
Esta solución me gusta más porque:
fuente
Seguí @barwin respuesta y comprobado cómo las pruebas unitarias se pueden hacer con recableado módulo. Puedo confirmar que esta solución simplemente funciona.
El módulo debe requerirse en dos partes: una pública y una privada. Para funciones públicas, puede hacerlo de manera estándar:
Para ámbito privado:
Para saber más sobre el tema, creé un ejemplo de trabajo con pruebas de módulo completo, las pruebas incluyen alcance privado y público.
Para obtener más información, le recomiendo que consulte el artículo ( https://medium.com/@macsikora/how-to-test-private-functions-of-es6-module-fb8c1345b25f ) que describe completamente el tema, incluye ejemplos de código.
fuente
Sé que esta no es necesariamente la respuesta que está buscando, pero lo que he encontrado es que la mayoría de las veces si vale la pena probar una función privada, vale la pena estar en su propio archivo.
Por ejemplo, en lugar de tener métodos privados en el mismo archivo que los públicos, como este ...
src / thing / PublicInterface.js
... lo dividiste así:
src / thing / PublicInterface.js
src / thing / internal / helper1.js
src / thing / internal / helper2.js
De esa manera, puede probar fácilmente
helper1
yhelper2
tal cual, sin usar Rewire y otras "magias" (que, según he descubierto, tienen sus propios puntos de dolor durante la depuración, o cuando intenta avanzar hacia TypeScript, sin mencionar que son más pobres) comprensibilidad para nuevos colegas). Y estar en una subcarpeta llamadainternal
, o algo así, ayudará a evitar su uso accidental en lugares no deseados.PD: Otro problema común con los métodos de "privado" es que si quieres prueba
publicMethod1
ypublicMethod2
y burlas de los ayudantes, de nuevo, que normalmente necesita algo así como Recablear de hacer eso. Sin embargo, si están en archivos separados, puede usar Proxyquire para hacerlo, que, a diferencia de Rewire, no necesita ningún cambio en su proceso de compilación, es fácil de leer y depurar, y funciona bien incluso con TypeScript.fuente
Para hacer que los métodos privados estén disponibles para las pruebas, hago esto:
fuente