tipos - static class javascript
Jasmine-Espiando una llamada de método dentro de un constructor (2)
Quiero probar si se llama al siguiente método en mi constructor de objetos Javascript. Por lo que he visto en la documentación de Jasmine, puedo espiar un método constructor y puedo espiar los métodos después de que un objeto ha sido instanciado, pero parece que no puedo espiar un método antes de construir el objeto.
El objeto:
Klass = function() {
this.called_method();
};
Klass.prototype.called_method = function() {
//method to be called in the constructor.
}
Quiero hacer algo como esto en la especificación:
it(''should spy on a method call within the constructor'', function() {
spyOn(window, ''Klass'');
var obj = new Klass();
expect(window.Klass.called_method).toHaveBeenCalled();
});
En general, estoy de acuerdo con la respuesta anterior de Dave Newton. Sin embargo, hay algunos casos extremos en este enfoque que debes considerar.
Tome una variación de la solución de Dave, con otro caso de prueba:
// production code
var Klass = function() {
this.call_count = 0;
this.called_method();
};
Klass.prototype.called_method = function() {
++this.call_count;
};
// test code
describe("The Klass constructor", function() {
it("should call its prototype''s called_method", function() {
spyOn(Klass.prototype, ''called_method'');
var k = new Klass();
expect(k.called_method).toHaveBeenCalled();
});
it(''some other test'', function() {
var k = new Klass();
expect(k.call_count).toEqual(1);
});
});
La segunda prueba fallará porque la configuración del espía en la primera prueba persiste a través de los límites de la prueba en el segundo método; called_method no incrementa call_count, por lo que this.call_count no es igual a 1. También es posible crear escenarios con falsos positivos, pruebas que pasan, que no deberían.
Además de esto, como el espía permanece, cuantas más instancias de Klass se creen, más grande será el montón de memoria que consumirá el espía, ya que el espía registrará cada llamada en llamado_metodo. Probablemente esto no sea un problema en la mayoría de las circunstancias, pero debe tenerlo en cuenta, por las dudas.
Una solución simple a este problema sería asegurarse de que el espía se elimine después de que se haya utilizado. Puede parecer un poco feo, pero algo como esto funciona:
// test code
describe("The Klass constructor", function() {
it("should call its prototype''s called_method", function() {
var spy = jasmine.createSpy(''called_method'');
var method = Klass.prototype.called_method;
Klass.prototype.called_method = spy;
var k = new Klass();
expect(spy).toHaveBeenCalled();
Klass.prototype.called_method = method;
});
[NOTA: una pequeña opinión para finalizar] Una mejor solución sería cambiar la forma en que escribe el código de producción para hacer que el código sea más fácil de probar. Como regla general, espiar prototipos es probablemente un olor codificado a evitar. En lugar de crear instancias de dependencias en el constructor, inyéctelas. En lugar de hacer la inicialización en el constructor, diferir a un método init apropiado.
Espía directamente en el método prototipo:
describe("The Klass constructor", function() {
it("should call its prototype''s called_method", function() {
spyOn(Klass.prototype, ''called_method''); //.andCallThrough();
var k = new Klass();
expect(Klass.prototype.called_method).toHaveBeenCalled();
});
});