Tengo un servicio Angular que importa una dependencia de terceros. Llamo a la dependencia para que me dé la huella digital del navegador que luego se almacena en el servicio.

No estoy seguro de cómo simular esta dependencia en la prueba, por lo que puedo afirmar que se ha llamado y simular un valor de retorno.

Este es el servicio:

import { Inject, Injectable } from '@angular/core';
import * as Fingerprint2 from 'fingerprintjs2';

@Injectable()
export class ClientInfoService {
    public fingerprint: string | null = null;

    constructor() {
    }

    createFingerprint(): any {
        return new Fingerprint2();
    }

    setFingerprint(): void {
        let fprint = this.createFingerprint();
        setTimeout(() => fprint.get(hash => this.fingerprint = hash), 500);
    }

    getFingerprint(): string | null {
        return this.fingerprint;
    }

}

Este es el código de prueba actual:

import { TestBed } from '@angular/core/testing';
import { ClientInfoService } from './client-info.service';

describe('Client Info Service', () => {
    const hash = 'a6e5b498951af7c3033d0c7580ec5fc6';
    let service: ClientInfoService;

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [ClientInfoService],
        });
        service = TestBed.get(ClientInfoService);
    });

    test('should be defined', () => {
        expect(service).toBeDefined();
    });


    describe('get the fingerprint', () => {

        test('it should be null', () => {
            let fprint = service.getFingerprint();
            expect(fprint).toBeNull();
        });

        test('it should be the hash value', () => {
            service.fingerprint = hash;
            let fprint = service.getFingerprint();
            expect(fprint).toEqual(hash);
        });

    test('it should get the hash value after setting', () => {
        jest.useFakeTimers();
        service.createFingerprint = jest.fn().mockReturnValue(() => {
            return {
                get: function (cb) {
                    return cb(hash);
                }
            };
        });
        spyOn(service, 'createFingerprint');
        service.setFingerprint();
        jest.runAllTimers();
        expect(service.createFingerprint).toHaveBeenCalled();
        expect(service.fingerprint).toEqual(hash);
    });

    });

});
1
RyanP13 16 oct. 2018 a las 15:57

2 respuestas

La mejor respuesta

Me las arreglé para lograr esto con la siguiente especificación. Usé espías y devolví valores para burlarme de la creación de huellas digitales.

import { TestBed } from '@angular/core/testing';
import { ClientInfoService } from './client-info.service';

describe('Client Info Service', () => {
    const hash = 'a6e5b498951af7c3033d0c7580ec5fc6';
    let service: ClientInfoService;

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [ClientInfoService],
        });
        service = TestBed.get(ClientInfoService);
    });

    test('should be defined', () => {
        expect(service).toBeDefined();
    });

    test('it should set the fingerprint', () => {
        jest.useFakeTimers()
        let cb = (h) => {return h;};
        spyOn(service, 'createFingerprint').and.returnValue({
            get: (cb) => {
                return cb(hash);
            },
        });
        service.setFingerprint();
        jest.runAllTimers();
        expect(service.createFingerprint).toHaveBeenCalled();
        expect(service.fingerprint).toEqual(hash);
    });

    test('it should get the fingerprint', () => {
        let fprint = service.getFingerprint();
        expect(fprint).toEqual(service.fingerprint);
    });

});
0
RyanP13 18 oct. 2018 a las 09:36

No importaría terceros directamente al servicio, ya que es difícil probarlos por unidad (especialmente si están haciendo cosas complicadas como llamadas http o manipulación DOM, etc.)

Puede ser una buena idea crear un servicio Angular que funcione como una fábrica para terceros:

import * as Fingerprint2 from 'fingerprintjs2';

@Injectable()
export class FingerprintFactory {
    create(): any {
        return new Fingerprint2();
    }
}

Después de eso, podrías inyectar FingerprintFactory en tu ClientInfoService y usar su método create para crear Fingerprint2 instancia.

Además, será muy fácil simular FingerprintFactory en tu ClientInfoService

1
Lisetsky Val 1 nov. 2018 a las 12:18