Использование Жасмин, чтобы шпионить за функцией без объекта

154

Я новичок в Жасмин и только начал использовать его. У меня есть файл библиотеки JS с большим количеством функций, которые не связаны ни с одним объектом (то есть являются глобальными). Как мне следить за этими функциями?

Я пытался использовать окно / документ в качестве объекта, но шпион не работал, хотя функция была вызвана. Я также попытался обернуть его в поддельный объект следующим образом:

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

и проверить с

expect(fakeElement.fakeMethod).toHaveBeenCalled();

Это не работает, так как шпион не работал

Четтер Хуммин
источник

Ответы:

155

Если вы определяете свою функцию:

function test() {};

Тогда это эквивалентно:

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

Так spyOn(window, 'test')должно работать.

Если это не так, вы также должны быть в состоянии:

test = jasmine.createSpy();

Если ни один из них не работает, что-то еще происходит с вашей настройкой.

Я не думаю, что ваша fakeElementтехника работает из-за того, что происходит за кулисами. Оригинальный globalMethod по-прежнему указывает на тот же код. Шпионаж - это прокси, но только в контексте объекта. Если вы можете заставить свой тестовый код вызывать через fakeElement, он будет работать, но тогда вы сможете отказаться от глобальных fns.

NDP
источник
2
Это сработало! Я думаю, что ошибка, которую я делал ранее, заключалась в том, что я вызывал spyOn с методом () вместо метода. Спасибо!
Четтер Хуммин
3
У меня были некоторые проблемы с использованием spyOn (окно, «тест») с использованием chutzpah для запуска тестов как часть нашей автоматизации из-за того, что «окно» не было назначено. Использование jasmine.createSpy () обошло это.
Хеннерс
7
jasmine.createSpy () отлично сработал для меня. Спасибо!
dplass
1
Раньше test = jasmine.createSpy();шпионил за angularJs $anchroScrollработал отлично
Эдгар Мартинес
1
По какой-то причине я не могу найти какой-либо способ работы, но вполне возможно, что это потому, что я пытаюсь смоделировать существующую оконную функцию; $window.open(url, '_blank');с целью открытия новой вкладки (или окна в зависимости от настроек браузера). Как я должен быть уверен, что он вызывает эту функцию и проверяет, что она перемещается по нужному URL независимо от браузера?
CSS
71

Пользователи TypeScript:

Я знаю, что ОП спрашивал о javascript, но для всех пользователей TypeScript, которые сталкиваются с этим и хотят следить за импортированной функцией, вот что вы можете сделать.

В тестовом файле преобразуйте импорт функции из этого:

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

x = foo(y);

К этому:

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

x = FooFunctions.foo(y);

Тогда вы можете следить за FooFunctions.foo:)

spyOn(FooFunctions, 'foo').and.callFake(...);
// ...
expect(FooFunctions.foo).toHaveBeenCalled();
Александр Тейлор
источник
3
Спасибо за подсказку TypeScript. Должно быть одинаково для ES6 / Babel, но я не пробовал.
hgoebl
1
Кажется, это работает только в случае явного вызова функции с псевдонимом FooFunctions . У меня есть функция bar (), которая является фабрикой, возвращающей baz (), и я хочу проверить, что baz () вызывает foo (). Этот метод не работает в этом сценарии.
Ричард Мацен
4
Это будет работать, если псевдоним берется внутри foo_functions, export const FooFunctions = { bar, foo }; а импорт в тесте становится import { FooFunctions } from '../foo_functions'. Тем не менее, псевдоним по-прежнему необходимо явно использовать в частной реализации foo_functions, чтобы шпион работал. const result = FooFunctions.foo(params)// шпион сообщает о звонке const result = foo(params)// шпион сообщает, что не звонил
Ричард Мацен
2
Работал как шарм! Спасибо, вы сэкономили мне много времени!
SrAxi
1
Это больше не работаетError: <spyOn> : parseCookie is not declared writable or has no setter
Лин Ву
42

Есть 2 альтернативы, которые я использую (для жасмина 2)

Это не совсем ясно, потому что кажется, что функция на самом деле является подделкой.

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

Второй более многословный, более явный и «чище»:

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

-> Исходный код жасмина, чтобы увидеть второй аргумент

IxDay
источник
Это имеет немного больше смысла и разбивает его достаточно далеко, чтобы повторить с успехом. +1 от меня. Спасибо, C§
CSS
9

Очень простой способ:

import * as myFunctionContainer from 'whatever-lib';

const fooSpy = spyOn(myFunctionContainer, 'myFunc');
FlavorScape
источник
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();
            })

Это сработало для меня.

Sushil
источник
4
Пожалуйста, добавьте пояснение к своему ответу, сам по себе код не очень полезен для человека, задающего вопрос, если он не может понять, что происходит.
Chevybow
0

Мой ответ немного отличается от @FlavorScape тем, что в импортированном модуле была одна функция (экспорт по умолчанию), я сделал следующее:

import * as functionToTest from 'whatever-lib';

const fooSpy = spyOn(functionToTest, 'default');
IonicBurger
источник