2011-12-12 13 views
5

¿es posible utilizar el método spyon del framework de pruebas unitarias de Jasmine en un método privado de clases?usando Jasmines spyon con un método privado

La documentación ofrece este ejemplo, pero ¿se puede flexibilizar para una función privada?

describe("Person", function() { 
    it("calls the sayHello() function", function() { 
     var fakePerson = new Person(); 
     spyOn(fakePerson, "sayHello"); 
     fakePerson.helloSomeone("world"); 
     expect(fakePerson.sayHello).toHaveBeenCalled(); 
    }); 
}); 

Gracias de antemano

Respuesta

4

Ninguna causa que no puedo acceder a una función privada fuera del contexto de la instancia.

Por cierto, no es una buena idea espiar los objetos que quiere probar. Cuando se prueba si se llama a un método específico en su clase que desea probar, no dice nada. Digamos que escribió la prueba y se aprobó, dos semanas más tarde refactoriza algunas cosas en la función y agrega un error. Entonces tu prueba sigue siendo verde porque te llama la función. B

Los espías son útiles cuando trabajas con Dependency Injection, donde el constructor pasa todas las dependencias externas y no las crea en tu clase. Entonces digamos que tienes una clase que necesita un elemento dom. Normalmente, usarías un selector de jquery en la clase para obtener este elemento. ¿Pero cómo quieres probar que algo está hecho con ese elemento? Claro que puede agregarlo a sus páginas de prueba html. Pero también puede llamar a su clase pasando el elemento en el constructor. Al hacerlo, puede usar spy para verificar si su clase interactúa con ese elemento como esperaba.

+16

No es correcto decir 'no es una buena idea espiar objetos que quieres probar'. El uso de espías no se limita a verificar si no se llamó simplemente a una función y eso es todo. Puede usar espías para verificar valores devueltos, para reemplazar funciones completamente para casos de prueba, errores de lanzamiento, etc. Sugeriría leer la documentación de jazmín para una comprensión más completa. –

+1

no es una buena idea espiar! ?? ¡No puedes estar más equivocado! De acuerdo, estoy de acuerdo con Tim y deberías ver al doco, ¿quién votó esto? –

+0

Eso no es lo que dije. Está bien usar espías. Pero debes manejar el objeto que quieres probar como una caja negra. Solo prueba lo que entra y sale. No pruebe las partes internas de la caja negra, lo que haría si espíe los métodos del objeto bajo prueba. Así que espiar las devoluciones de llamada que pasas al objeto está totalmente bien. –

0

Si desea probar funciones privadas dentro de una clase, ¿por qué no agregar un constructor a su clase que indique que esas funciones privadas se devuelven?

tener una lectura a través de este para ver lo que quiero decir: http://iainjmitchell.com/blog/?p=255

He estado usando una idea similar y hasta el momento de su elaboración genial!

+5

Si publica su método privado ya no es privat.Por cierto, como describí en mi respuesta, no tiene mucho sentido probar el método privado. –

+0

Podemos estar de acuerdo no estar de acuerdo con eso. Nuestra base de código de JavaScript es enorme y solo mostramos un conjunto de funciones/propiedades públicas en algunas de nuestras clases. Se maneja mucha lógica en esas funciones privadas. Solo publico un método privado para que el marco de prueba tenga acceso a él. Si el constructor no se llama correctamente, entonces la función privada no se devuelve. – StevenMcD

+1

Hay un buen SO en este tema: http://stackoverflow.com/q/7075938/184883. –

3

si utiliza Typescript para sus objetos, la función no es realmente privada.
Todo lo que necesita es guardar el valor devuelto por la llamada spyOn y luego consultar su propiedad calls.

Al final de este código debería funcionar bien para usted (al menos a mí me funcionó):

describe("Person", function() { 
    it("calls the sayHello() function", function() { 
     var fakePerson = new Person(); 
     // save the return value: 
     var spiedFunction = spyOn(fakePerson, "sayHello"); 
     fakePerson.helloSomeone("world"); 
     // query the calls property: 
     expect(spiedFunction.calls.any()).toBeFalsy(); 
    }); 
}); 
+4

Recibo un error de tipo si intento llamar a una función no exportada (privada): 'Error: (33, 56) TS2345: El argumento de tipo '" sayHello "' no se puede asignar al parámetro de tipo '' sayGoodbye '' .' donde 'sayGoodbye' es un método público en' Person' y 'sayGoodbye' es privado. Tengo que lanzarlo a cualquiera ("sayHello" como cualquier) – FlavorScape

+0

Necesito más contexto aquí, parece que su tarea no está funcionando y no el acceso a la función privada. Pero intente acceder de esta manera: 'persona [" sayHello "]' en lugar de 'persona.sayHello' (si eso es lo que está haciendo). Esto no es una buena práctica, pero en casos excepcionales se perdona;) – jurl

1

Sólo añadir un parámetro genérico < cualquier> a la función SpyOn():

spyOn<any>(fakePerson, 'sayHello'); 

¡Funciona perfectamente!

Cuestiones relacionadas