Soy nuevo en la escritura de pruebas unitarias y necesito ayuda para probar parte de una función.

Mi función se ve así ...

getData() {
return this.parameters.map(p => {
        return {
            name: p.name,
            items: p.items.map(item => {

                const toTime = item.hasOwnProperty('end') ? moment.utc(item.end._d).unix() : null;
                const fromTime = item.hasOwnProperty('start') ? moment.utc(item.start._d).unix() : null;

                return {
                    id: item.id,
                    fromTime: fromTime,
                    toTime: toTime,
                };
            }),
        };
    });
}

Y hasta ahora mi prueba se ve así (jazmín)

describe('getData()', function() {
it('should return json data', function() {
    $ctrl.parameters = [{
        name: 'test',
        items: [{
            id: 1,
            fromTime: null,
            toTime: null
        }, {
            id: 13,
            fromTime: null,
            toTime: null

        }]
    }];

    expect($ctrl.getData()).toEqual([{
        name: 'test',
        items: [{
            id: 1,
            fromTime: null,
            toTime: null
        }, {
            id: 13,
            fromTime: null,
            toTime: null
        }]
    }]);
});
});

Esta prueba está funcionando / pasando, pero como puede ver, no estoy probando el ternario if / else que usa Moment.js. Básicamente, lo que hace el ternario es verificar si los elementos contienen una propiedad llamada start / end y, si es así, convertir ese valor en una marca de tiempo epoch / unix y asignarlo a toTime o fromTime. Entonces, si los elementos tuvieran una propiedad llamada final con un valor de 'Sat Oct 31 2015 00:00:00 GMT+0000 (GMT)', entonces se convertiría a '1446249600' y se asignaría a toTime

¡Ojalá eso lo explique! No estoy seguro de cómo escribir una prueba y agradecería cualquier ayuda / sugerencia.

14
Jose the hose 14 dic. 2016 a las 16:53

1 respuesta

La mejor respuesta

La opción más simple es simplemente construir un par de fechas de ejemplo manualmente para la entrada. Por ejemplo:

$ctrl.parameters = [{
    name: 'test',
    items: [{
        id: 1,
        start: moment.utc('2017-01-01T01:00:00'),
        end: moment.utc('2017-01-01T06:00:00')
    }, {
        id: 13,
        start: moment.utc('2017-01-02T08:00:00'),
        end: null

    }]
}];

(Tenga en cuenta que en el ejemplo anterior, cambié fromTime y toTime a start y end, respectivamente, ya que eso es lo que getData espera para la entrada. )

Luego, averigüe sus marcas de tiempo de Unix. Puede hacer esta parte externamente; por ejemplo, acabo de abrir las herramientas de desarrollo del navegador (F12) en el sitio web moment.js, evalué las siguientes declaraciones en la consola y tomé los valores de la marca de tiempo:

moment.utc('2017-01-01T01:00:00').unix()
moment.utc('2017-01-01T06:00:00').unix()
moment.utc('2017-01-02T08:00:00').unix()

Finalmente, de vuelta en la prueba unitaria, solo verifique que las marcas de tiempo coincidan con los valores esperados:

expect($ctrl.getData()).toEqual([{
  name: 'test',
  items: [{
    id: 1,
    fromTime: 1483232400,
    toTime: 1483250400
  }, {
    id: 13,
    fromTime: 1483344000,
    toTime: null
  }]
}]);

Alternativamente, si prefiere no tener marcas de tiempo codificadas en sus pruebas unitarias, puede almacenar cada fecha de ejemplo en su propia variable (por ejemplo, start1, end1), y luego comparar con, por ejemplo, start1.unix():

// Arrange
const start1 = moment.utc('2017-01-01T01:00:00');
const end1 = moment.utc('2017-01-01T06:00:00');
const start2 = moment.utc('2017-01-02T08:00:00');
$ctrl.parameters = [{
    name: 'test',
    items: [{
        id: 1,
        start: start1,
        end: end1
    }, {
        id: 13,
        start: start2,
        end: null

    }]
}];

// Act
const result = $ctrl.getData();

// Assert
expect(result).toEqual([{
  name: 'test',
  items: [{
    id: 1,
    fromTime: start1.unix(),
    toTime: end1.unix()
  }, {
    id: 13,
    fromTime: start2.unix(),
    toTime: null
  }]
}]);

Eso está perfectamente bien, ya que la prueba unitaria está destinada a probar su código, no moment.js. Tu decides.

Tenga en cuenta también que estoy usando el patrón Arrange-Act-Assert para organizar la prueba. Nuevamente, depende de usted, pero una vez que sus pruebas unitarias comienzan a complicarse, eso tiende a hacer que las cosas sean más fáciles de seguir.

De cualquier manera, deberá cambiar la forma en que calcula toTime y fromTime en su método getData, ya que el código tal como está escrito no funcionará si pasa null para cualquiera start o end. En particular, item.hasOwnProperty('start') devolverá verdadero si pasa un valor null para start, pero generará un error porque intenta evaluar item.start._d. En su lugar, recomiendo cambiar esas 2 líneas a lo siguiente:

const toTime = item.end ? moment.utc(item.end._d).unix() : null;
const fromTime = item.start ? moment.utc(item.start._d).unix() : null;

También desaconsejaría el uso de la propiedad _d del objeto de momento, ya que es una variable interna (privada). Dado que start y end ya son objetos de momento, es posible que en su lugar pueda hacer esto:

const toTime = item.end ? item.end.unix() : null;
const fromTime = item.start ? item.start.unix() : null;

Un ejemplo completo de jsbin que contiene todos los cambios recomendados anteriormente está disponible aquí:

https://jsbin.com/xuruwuzive/edit?js,output

Tenga en cuenta que se tuvieron que hacer algunos ajustes para que se ejecute fuera del contexto de AngularJS (haga que getData sea una función independiente que acepte sus parámetros directamente, en lugar de a través de $ctrl).

7
Sergey K 1 ene. 2017 a las 08:37
¡Gracias! Esta funcionando. ¡Y gracias también por la muestra!
 – 
Jose the hose
3 ene. 2017 a las 17:42