使用 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_functionsexport 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 1 中监视 Falcor 数据模型构造函数