w3schools ejemplos buttons javascript unit-testing sinon

javascript - ejemplos - i html



¿Cómo probar múltiples llamadas a la misma función con diferentes parámetros? (2)

Supongo que tengo una función como esta:

function foo () { obj.method(1); obj.method(2); obj.method(3); }

Para probarlo quiero hacer 3 pruebas (usando Mocha TDD y Sinon):

test(''medthod is called with 1'', function () { var expectation = sinon.mock(obj).expects(''method'').once().withExactArgs(1); foo(); expectation.verify(); }); test(''medthod is called with 2'', function () { var expectation = sinon.mock(obj).expects(''method'').once().withExactArgs(2); foo(); expectation.verify(); }); test(''medthod is called with 3'', function () { var expectation = sinon.mock(obj).expects(''method'').once().withExactArgs(3); foo(); expectation.verify(); });

El uso de este sistema sinon falla con el mensaje de "llamada inesperada" en cada prueba.

Lo he resuelto uniendo las pruebas de árbol en una:

test(''medthod is called with 1, 2 and 3'', function () { var mock = sinon.mock(obj); mock.expects(''method'').once().withExactArgs(1); mock.expects(''method'').once().withExactArgs(2); mock.expects(''method'').once().withExactArgs(3); foo(); mock.verify(); });

Pero quiero tener tres pruebas y no una con tres afirmaciones / expectativas.

¿Cómo se puede lograr esto?


Como siempre, cuando hay algo extraño en una prueba, el problema está en el código que se está probando .

En este caso sufrimos de acoplamiento. Actualmente la función tiene dos responsabilidades:

  • Decidir los datos a utilizar.
  • Llama al método con los datos.

Para resolver esto, debemos dividir las responsabilidades en dos funciones / objetos / clases y luego probar cada una por separado. Por ejemplo, una posibilidad podría ser:

  • La primera función (una que genera y devuelve los datos) se probaría verificando que los datos devueltos coincidan con nuestras expectativas.

  • La segunda función (la nuestra original) tendría una prueba de verificación de que llama al generador de datos, luego una prueba de que envía los datos correctamente a la función esperada y una tercera que comprueba que llama a las funciones tantas veces como sea necesario. los datos.

El código sería algo como esto:

function foo() { dataGenerator.generate().forEach(function (item) { obj.method(item); }) } dataGenerator.generate = function () { return [1,2,3]; };

Y las pruebas:

test(''generateData is called'', function () { var expectation = sinon.mock(dataGenerator).expects(''generate'').once(); foo(); expectation.verify(); }); test(''method is called with the correct args'', function () { var expectedArgs = 1; sinon.stub(dataGenerator, "generate").returns([expectedArgs]); var expectation = sinon.mock(obj).expects(''method'').once().withExactArgs(expectedArgs); foo(); expectation.verify(); }); test(''method is called as many times as the amount of data'', function () { sinon.stub(dataGenerator, "generate").returns([1,2]); var expectation = sinon.mock(obj).expects(''method'').twice(); foo(); expectation.verify(); }); test(''dataGenerator.generate returns [1,2,3]'', function () { var expected = [1,2,3]; var result = dataGenerator.generate(); assert.equal(result, expected) });

Tenga en cuenta que la tercera prueba solo verifica la cantidad de veces que se llama al método. La segunda prueba ya ha verificado que los datos se pasan correctamente y la cuarta prueba los datos en sí.


Esta es una versión hinchada, pero esta solución podría funcionar. No estoy seguro de si todavía lo necesitas, pero lo estoy agregando aquí. http://jsfiddle.net/reyuto/jhkL7j34/

obj = { method: function (param) {} }; function foo() { obj.method(1); obj.method(2); obj.method(3); } mock = sinon.mock(obj); QUnit.test(''method is called with 1'', function () { var expectation1 = mock.expects(''method'').once().withExactArgs(1); var expectation2 = mock.expects(''method'').atLeast(2); foo(); expectation1.verify(); expectation2.verify(); }); QUnit.test(''method is called with 2'', function () { var expectation1 = mock.expects(''method'').atLeast(1); var expectation2 = mock.expects(''method'').once().withExactArgs(2); var expectation3 = mock.expects(''method'').atLeast(1); foo(); expectation1.verify(); expectation2.verify(); expectation3.verify(); }); QUnit.test(''method is called with 3'', function () { var expectation1 = mock.expects(''method'').once().withExactArgs(3); var expectation2 = mock.expects(''method'').atLeast(2); foo(); expectation1.verify(); expectation2.verify(); });