Usare Jasmine per spiare una funzione senza un oggetto


154

Sono nuovo di Jasmine e ho appena iniziato a usarlo. Ho un file js della libreria con molte funzioni che non sono associate a nessun oggetto (cioè sono globali). Come faccio a spiare queste funzioni?

Ho provato a usare window / document come oggetto, ma la spia non ha funzionato anche se è stata chiamata la funzione. Ho anche provato a avvolgerlo in un oggetto falso come segue:

var fakeElement = {};
fakeElement.fakeMethod = myFunctionName;
spyOn(fakeElement, "fakeMethod");

e prova con

expect(fakeElement.fakeMethod).toHaveBeenCalled();

Questo non funziona neanche perché la spia non ha funzionato

Risposte:


155

Se stai definendo la tua funzione:

function test() {};

Quindi, questo equivale a:

window.test = function() {}  /* (in the browser) */

Quindi spyOn(window, 'test')dovrebbe funzionare.

In caso contrario, dovresti anche essere in grado di:

test = jasmine.createSpy();

Se nessuno di questi funziona, sta succedendo qualcos'altro nella configurazione.

Non credo che la tua fakeElementtecnica funzioni a causa di ciò che accade dietro le quinte. Il globalMethod originale punta ancora allo stesso codice. Ciò che fa lo spionaggio è proxy, ma solo nel contesto di un oggetto. Se riesci a far chiamare il tuo codice di prova tramite fakeElement, funzionerebbe, ma allora potresti rinunciare a fns globali.


2
Ha funzionato! Penso che l'errore che stavo facendo in precedenza fosse che stavo chiamando spyOn con method () invece di method. Grazie!
Chetter Hummin

3
Ho avuto dei problemi usando spyOn (window, 'test') usando chutzpah per eseguire i test come parte della nostra automazione a causa della mancata assegnazione di 'window'. Utilizzando jasmine.createSpy () aggirato questo.
Henners,

7
jasmine.createSpy () ha funzionato perfettamente per me. Grazie!
dplass

1
usato test = jasmine.createSpy();per spiare AngularJs $anchroScrollfunzionava perfettamente
Edgar Martinez,

1
Per qualche motivo non riesco a lavorare in entrambi i modi, ma potrebbe essere del tutto possibile perché sto cercando di deridere una funzione di finestra esistente; $window.open(url, '_blank');con l'intenzione di aprire una nuova scheda (o finestra a seconda della configurazione del browser). Come devo fare per assicurarmi che stia chiamando questa funzione e verificare che stia navigando all'URL giusto indipendentemente dal browser?
CSS,

71

Utenti di TypeScript:

So che l'OP ha chiesto javascript, ma per tutti gli utenti TypeScript che si imbattono in questo e vogliono spiare una funzione importata, ecco cosa puoi fare.

Nel file di test, converti l'importazione della funzione da questo:

import {foo} from '../foo_functions';

x = foo(y);

A questa:

import * as FooFunctions from '../foo_functions';

x = FooFunctions.foo(y);

Quindi puoi spiare FooFunctions.foo:)

spyOn(FooFunctions, 'foo').and.callFake(...);
// ...
expect(FooFunctions.foo).toHaveBeenCalled();

3
Grazie per il suggerimento TypeScript. Dovrebbe essere uguale per ES6 / Babel, ma non l'ho provato.
hgoebl,

1
Sembra funzionare solo se chiama la funzione esplicitamente con l'alias FooFunctions . Ho una barra delle funzioni () che è una factory che restituisce baz () e voglio testare che baz () chiama foo (). Questo metodo non sembra funzionare in quello scenario.
Richard Matsen,

4
Questo funzionerà se l'alias viene preso all'interno di foo_functions export const FooFunctions = { bar, foo }; e l'importazione nel test diventa import { FooFunctions } from '../foo_functions'. Tuttavia, l'alias deve ancora essere esplicitamente utilizzato nell'implementazione privata di foo_functions affinché la spia funzioni. const result = FooFunctions.foo(params)// spia spia chiama const result = foo(params)// spia spia non chiama
Richard Matsen

2
Ha funzionato come un fascino! Grazie, mi hai risparmiato un sacco di tempo!
SrAxi,

1
Questo non funziona più ha ottenuto unError: <spyOn> : parseCookie is not declared writable or has no setter
Ling Vu

42

Esistono 2 alternative che utilizzo (per jasmine 2)

Questo non è del tutto esplicito perché sembra che la funzione sia in realtà un falso.

test = createSpy().and.callFake(test); 

Il secondo più dettagliato, più esplicito e "più pulito":

test = createSpy('testSpy', test).and.callThrough();

-> codice sorgente jasmine per vedere il secondo argomento


Questo ha un po 'più senso e lo esplode abbastanza da duplicare con successo. +1 da me. Grazie, C§
CSS,

9

Un modo molto semplice:

import * as myFunctionContainer from 'whatever-lib';

const fooSpy = spyOn(myFunctionContainer, 'myFunc');

1
import * as saveAsFunctions from 'file-saver';
..........
....... 
let saveAs;
            beforeEach(() => {
                saveAs = jasmine.createSpy('saveAs');
            })
            it('should generate the excel on sample request details page', () => {
                spyOn(saveAsFunctions, 'saveAs').and.callFake(saveAs);
                expect(saveAsFunctions.saveAs).toHaveBeenCalled();
            })

Questo ha funzionato per me.


4
Aggiungi una spiegazione alla tua risposta, il codice da solo non è di grande aiuto per la persona che pone la domanda se non riesce a capire cosa sta succedendo.
chevybow,

0

La mia risposta differisce leggermente da @FlavorScape in quanto avevo una singola funzione (esportazione predefinita) nel modulo importato, ho fatto quanto segue:

import * as functionToTest from 'whatever-lib';

const fooSpy = spyOn(functionToTest, 'default');
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.