unitarios unit test nodejs example javascript jquery unit-testing jasmine sinon

javascript - unit - sinon stub example



Apagar una llamada jQuery selector? (3)

Estoy tratando de mejorar en la unidad de pruebas de mi JavaScript. Tengo el siguiente código:

var categoryVal = $(''#category'').val(); if (categoryVal === '''') { doSomething(); }

Mi corredor de prueba no tiene la entrada #category en la página, así que, ¿cómo puedo apagar / simular el selector jQuery aquí? He examinado tanto la documentación de sinon como de sinon , pero no puedo averiguar cómo hacer que funcionen aquí, ya que sus talones operan en objetos, lo que no es $ .


Aquí hay una guía bastante buena para probar sus vistas si está utilizando Backbone.js y Jasmin. Desplácese hasta la sección Ver.

http://tinnedfruit.com/2011/04/26/testing-backbone-apps-with-jasmine-sinon-3.html

Es cierto que los talones operan sobre objetos. Supongo que el punto de crear un talón de vista como tal.

this.todoViewStub = sinon.stub(window, "TodoView") .returns(this.todoView);

Es solo para poder luego renderizar la vista.

this.view.render();

En otras palabras, agregue el div ''#category'' al DOM del testrunner, para que $ pueda actuar sobre él. Si su div "#category" no está en esta vista, entonces probablemente pueda crear una página test.html en la que ejecute su prueba aislada. Este es un patrón común en el marco de Javascript MVC que estoy más acostumbrado a ese Backbone.

Aquí hay un ejemplo simple de la estructura de la aplicación JMVC:

/todo /models todo.js /list /views init.tmpl listItem.tmpl list.css list.js (Controller) unitTest.js (Tests for your list.) list_test.html (A html for your unit tests to run on.)

Teniendo esta configuración, simplemente puedes incluir el div "#category" en tu list_test.html si ya no lo tienes dentro de una de las vistas.


El problema aquí es que $() es una función que devuelve un objeto con el método val() . Por lo tanto, debe marcar $ () para devolver un objeto aplastado que tenga el método val.

$ = sinon.stub(); $.withArgs(''#category'').returns(sinon.stub({val: function(){}}));

Pero el error principal aquí es dejar que el código que desea probar llame a la función $ () para crear nuevas instancias. ¿Por qué? Es una buena práctica no crear nuevas instancias en su clase, sino pasarlas al constructor. Digamos que tiene una función que obtendrá un valor de una entrada, la duplicará y la escribirá en otra:

function doubleIt(){ $(''#el2'').val((''#el1'').val() *2); }

En este caso, creas 2 objetos nuevos llamando a $() . Ahora tienes que pegar $() para devolver un simulacro y un talón. Usando el siguiente ejemplo puedes evitar esto:

function doubleIt(el1, el2){ el2.val(el1.val() *2); }

Mientras que, en el primer caso, debe aplastar $ para devolver un talón, en el segundo caso puede pasar fácilmente un talón y un espía a su función.

Así que la prueba de sinon para el segundo se vería así:

var el1 = sinon.stub({val: function(){}}); el1.returns(2); var el2 = sinon.spy({val: function(){}}, ''val'') doubleIt(el1, el2) assert(el2.withArgs(4).calledOnce)

Por lo tanto, como no tiene elementos de dominio aquí, simplemente puede probar la lógica de su aplicación sin necesidad de crear el mismo dominio que en su aplicación.


jQuery usa el motor selector de css Sizzle debajo del capó y se desacopló, por lo que solo hay algunos lugares donde se engancha. Puede interceptarlo para evitar cualquier interacción con el dom.

jQuery.find es el importante que debes modificar para responder con lo que quieras. Sinon podría usarse aquí o temporalmente cambiar la función.

p.ej

existingEngine = jQuery.find jQuery.find = function(selector){ console.log(selector) } $(".test") //>> ".test" jQuery.find = existingEngine

También podría aplicar una condición de captura específica con un respaldo.

existingEngine = jQuery.find jQuery.find = function(selector){ if(selector==''blah''}{ return "test"; } return existingEngine.find.apply(existingEngine, arguments) }

En mi trabajo reciente, he creado un objeto ficticio que responde como un nodo dom y lo envolví en un objeto jQuery. Esto responderá a val () correctamente y tendrá todos los métodos de jquery presentes que espera. En mi caso, simplemente estoy extrayendo valores de un formulario. Si está realizando una manipulación real, es posible que tenga que ser más inteligente que esto, tal vez creando un nodo dom temporal con jQuery que represente lo que esperaba.

obj = { value: "blah", type: "text", nodeName: "input", } $(obj).val(); // "blah"