web-dev-qa-db-fra.com

Comment stub une méthode de jasmine mock object?

Selon la documentation de Jasmine, une maquette peut être créée comme ceci:

jasmine.createSpyObj(someObject, ['method1', 'method2', ... ]);

Comment stub vous l'une de ces méthodes? Par exemple, si vous voulez tester ce qui se passe quand une méthode lève une exception, comment feriez-vous cela?

61
Adelin

Vous devez chaîner method1, method2 Comme EricG a commenté, mais pas avec andCallThrough() (ou and.callThrough() dans la version 2.0). Il va déléguer à la mise en œuvre réelle.

Dans ce cas, vous devez chaîner avec and.callFake() et transmettre la fonction que vous souhaitez appeler (vous pouvez générer une exception ou ce que vous voulez):

var someObject = jasmine.createSpyObj('someObject', [ 'method1', 'method2' ]);
someObject.method1.and.callFake(function() {
    throw 'an-exception';
});

Et puis vous pouvez vérifier:

expect(yourFncCallingMethod1).toThrow('an-exception');
102
zbynour

Si vous utilisez TypeScript, il est utile de convertir la méthode en Jasmine.Spy. Dans la réponse ci-dessus (curieusement, je n'ai pas de représentant pour commenter):

(someObject.method1 as Jasmine.Spy).and.callFake(function() {
  throw 'an-exception';
});

Je ne sais pas si je suis trop ingénieur, car je manque de connaissances ...

Pour TypeScript, je veux:

  • Intellisense du type sous-jacent
  • La possibilité de se moquer des méthodes utilisées dans une fonction

J'ai trouvé cela utile:

namespace Services {
    class LogService {
        info(message: string, ...optionalParams: any[]) {
            if (optionalParams && optionalParams.length > 0) {
                console.log(message, optionalParams);
                return;
            }

            console.log(message);
        }
    }
}

class ExampleSystemUnderTest {
    constructor(private log: Services.LogService) {
    }

    doIt() {
        this.log.info('done');
    }
}

// I export this in a common test file 
// with other utils that all tests import
const asSpy = f => <jasmine.Spy>f;

describe('SomeTest', () => {
    let log: Services.LogService;
    let sut: ExampleSystemUnderTest;

    // ARRANGE
    beforeEach(() => {
        log = jasmine.createSpyObj('log', ['info', 'error']);
        sut = new ExampleSystemUnderTest(log);
    });

    it('should do', () => {
        // ACT
        sut.doIt();

        // ASSERT
        expect(asSpy(log.error)).not.toHaveBeenCalled();
        expect(asSpy(log.info)).toHaveBeenCalledTimes(1);
        expect(asSpy(log.info).calls.allArgs()).toEqual([
            ['done']
        ]);
    });
});
16
Eric Swanson

En me basant sur la réponse de @Eric Swanson, j'ai créé une fonction plus lisible et documentée à utiliser dans mes tests. J'ai également ajouté un type de sécurité en tapant le paramètre en tant que fonction.

Je recommanderais de placer ce code quelque part dans une classe de test commune, afin de pouvoir l'importer dans tous les fichiers de test qui en ont besoin.

/**
 * Transforms the given method into a jasmine spy so that jasmine functions
 * can be called on this method without TypeScript throwing an error
 *
 * @example
 * `asSpy(translator.getDefaultLang).and.returnValue(null);`
 * is equal to
 * `(translator.getDefaultLang as jasmine.Spy).and.returnValue(null);`
 *
 * This function will be mostly used in combination with `jasmine.createSpyObj`, when you want
 * to add custom behavior to a by jasmine created method
 * @example
 * `const translator: TranslateService = jasmine.createSpyObj('TranslateService', ['getDefaultLang'])
 * asSpy(translator.getDefaultLang).and.returnValue(null);`
 *
 * @param {() => any} method - The method that should be types as a jasmine Spy
 * @returns {jasmine.Spy} - The newly typed method
 */
export function asSpy(method: () => any): jasmine.Spy {
  return method as jasmine.Spy;
}

L'utilisation serait comme suit:

import {asSpy} from "location/to/the/method";

const translator: TranslateService = jasmine.createSpyObj('TranslateService', ['getDefaultLang']);
asSpy(translator.getDefaultLang).and.returnValue(null);
0
Mr.wiseguy