使用 Jasmine 监视没有对象的函数

Posted

技术标签:

【中文标题】使用 Jasmine 监视没有对象的函数【英文标题】:Using Jasmine to spy on a function without an object 【发布时间】:2012-03-19 14:09:23 【问题描述】:

我是 Jasmine 的新手,刚刚开始使用它。我有一个库 js 文件,其中包含许多与任何对象(即全局)无关的函数。我该如何监视这些功能?

我尝试使用窗口/文档作为对象,但即使调用了该函数,间谍也不起作用。我还尝试将其包装在一个假对象中,如下所示:

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

和测试

expect(fakeElement.fakeMethod).toHaveBeenCalled();

这也不起作用,因为间谍不起作用

【问题讨论】:

【参考方案1】:

如果你正在定义你的函数:

function test() ;

那么,这就相当于:

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

所以spyOn(window, 'test') 应该可以工作。

如果不是这样,您还应该能够:

test = jasmine.createSpy();

如果这些都不起作用,则说明您的设置正在进行其他操作。

我认为您的 fakeElement 技术不起作用,因为幕后发生的事情。原来的 globalMethod 仍然指向相同的代码。间谍所做的是代理它,但仅限于对象的上下文中。如果你可以让你的测试代码通过 fakeElement 调用它会起作用,但是你可以放弃全局 fns。

【讨论】:

成功了!我认为我之前犯的错误是我用 method() 而不是 method 调用了 spyOn。谢谢! 我在使用 spyOn(window, 'test') 使用 chutzpah 运行测试时遇到了一些问题,这是我们自动化的一部分,因为没有分配 'window'。使用 jasmine.createSpy() 解决了这个问题。 jasmine.createSpy() 非常适合我。谢谢! 使用 test = jasmine.createSpy(); 监视 angularJs $anchroScroll 工作完美 由于某种原因,我无法以任何一种方式工作,但完全有可能是因为我正在尝试模拟现有的窗口函数; $window.open(url, '_blank'); 旨在打开一个新选项卡(或窗口,具体取决于浏览器设置)。无论浏览器如何,我应该如何确保它调用此函数并验证它是否导航到正确的 url?【参考方案2】:

TypeScript 用户:

我知道 OP 询问了有关 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();

【讨论】:

感谢 TypeScript 提示。对于 ES6/Babel 应该是一样的,但是我没试过。 似乎只有在使用别名 FooFunctions 显式调用函数时才有效。我有一个函数 bar(),它是一个返回 baz() 的工厂,并且想要测试 baz() 调用 foo()。这种方法在那种情况下似乎不起作用。 如果别名在 foo_functions export const FooFunctions = bar, foo ; 中使用,并且测试中的导入变为 import FooFunctions from '../foo_functions'.,这将起作用。但是,别名仍然需要在 foo_functions 私有实现中显式使用,间谍才能工作. const result = FooFunctions.foo(params) // 间谍报告呼叫 const result = foo(params) // 间谍报告没有呼叫 工作就像一个魅力!谢谢,你为我节省了很多时间! 这行不通了,得到了Error: <spyOn> : parseCookie is not declared writable or has no setter【参考方案3】:

我使用了 2 个替代方案(对于 jasmine 2)

这个不是很明确,因为看起来这个函数实际上是假的。

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

第二个更详细、更明确、更“干净”:

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

->jasmine source code查看第二个参数

【讨论】:

这更有意义,并将其分解得足够远以成功复制。 +1 来自我。谢谢,C§【参考方案4】:

一个很简单的方法:

import * as myFunctionContainer from 'whatever-lib';

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

【讨论】:

【参考方案5】:
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();
            )

这对我有用。

【讨论】:

请在您的答案中添加解释,如果提问者无法理解发生了什么,代码本身并没有太大帮助。【参考方案6】:

我们通常遵循的方法如下:

utils.ts 用于所有全局实用程序的文件:

function globalUtil() 
  // some code

abc.component.ts:

function foo 
  // some code
  globalUtil();  // calls global function from util.ts

在为 function foo () 编写 Jasmine 测试时,您可以按如下方式监视 globalUtil 函数:

abc.component.spec.ts:

import * as SharedUtilities from 'util.ts';

it('foo', () =>

  const globalUtilSpy = jasmine.createSpy('globalUtilSpy');
  spyOnProperty(SharedUtilities, "globalUtilSpy").and.returnValue(globalUtilSpy);
  
  foo();
  expect(globalUtilSpy).toHaveBeenCalled();
);

【讨论】:

【参考方案7】:

我的回答与@FlavorScape 略有不同,因为我在导入的模块中有一个(默认导出)函数,我做了以下操作:

import * as functionToTest from 'whatever-lib';

const fooSpy = spyOn(functionToTest, 'default');

【讨论】:

【参考方案8】:

我想这是最简单的方法:

const funcSpy = spyOn(myFunc, 'call');

【讨论】:

以上是关于使用 Jasmine 监视没有对象的函数的主要内容,如果未能解决你的问题,请参考以下文章

使用 Jasmine 监视私有变量的属性/函数

如何在 Jasmine 1 中监视 Falcor 数据模型构造函数

Jasmine - 监视在同一文件中调用的函数

Jasmine:监视一个名为 X 次的函数,并获得第 n 次调用

如何对 DOM 操作进行单元测试(使用 jasmine)

错误:找不到模块 'jasmine-expect' [量角器]