我使用 webpack 3 进行了 jasmine 测试。现在我尝试将其与 webpack 4 一起使用,但遇到了一些问题。
首先我遇到了spyOn功能的问题。
错误::myFunction 未声明为可写或没有设置器
我找到了一些关于此问题的解决方法的文章:spy-on-getter-and-setter
我将 spyOn 更改为 spyOnProperty 但没有运气。现在我遇到了问题
> 错误::myFunction 未声明为可配置
我的代码是用js编写的,如下所示:
import * as FocusServiceSpy from '../focus/FocusService';
describe('#onLinkClick', function() {
it('should call myFunction', () => {
spyOnProperty(FocusServiceSpy, 'myFunction', 'get');
expect(FocusServiceSpy.myFunction).toHaveBeenCalled();
});
}
你知道这可能是什么问题吗?
更新1:
我应该更具描述性。我想创建监视 FocusService 的功能。该服务只有一种名为 myFunction 的方法。我唯一想要实现的就是确保这个方法会被调用。
现在我把它改成这样并且有错误:
>TypeError:对象不是构造函数(评估“new FocusService()”)(第 180 行)
describe('#onLinkClick', function() {
const FocusService = require('../focus/FocusService');
it('should call myFunction', () => {
const service = new FocusService();
spyOnProperty(service, 'myFunction').and.callThrough();
... (do some action)
expect(service.myFunction).toHaveBeenCalled();
});
}
FocusService 看起来像这样:
export function myFunction(arg) {
... (do some action)
}
在你的单元测试中,我可以看到几个问题。首先,您需要了解
spyOnProperty
将属性上的 spy
安装到现有对象上,但它不会调用 getter
本身。
您不创建对象也不将其提供给
spyOnProperty
。
您使用函数名称而不是属性来调用
spyOnProperty
名字。
您的测试可以按如下方式构建:
it('should call myFunction', () => {
// given
const service = new FocusService();
const spy = spyOnProperty(service , 'myProperty', 'get').and.callThrough();
// when
const myProperty = service.myProperty;
// then
expect(myProperty).toBe(<expected value>);
expect(spy).toHaveBeenCalled();
});
当我尝试将项目从 Angular 8 升级到 9 时,我遇到了同样的问题,我在 Google 上找不到答案,但是我找到了一种在我的项目中解决它的方法。
在
tsconfig.json
中,将 target
更改为 es5
。
示例:
{
"compilerOptions": {
...
"target": "es5",
...
}
}
就是这样!希望这可以帮助正在尝试找到解决方案的人。
在新版本的 Jasmine 中,不允许间谍变异,并且会为您尝试修改的间谍成员抛出上述错误。
不建议更改间谍属性的定义,因为 Jasmine 明确不允许成员可配置。
如果您不希望强制执行此限制,请将以下代码添加到您的入口测试文件中。
const defineProperty = Object.defineProperty;
Object.defineProperty = (o, p, c) => defineProperty(o, p, Object.assign({}, c ?? {}, { configurable: true }));
上面的代码强制将测试运行期间定义的每个属性标记为可配置。
在类定义文件中的导入之后添加
configure({ safeDescriptors: false });
,它可以与属性一起使用
定义一个
spyHack
实用函数,暂时覆盖Object.defineProperty
函数。
export class JasminHelper {
public spyHack(doSpying: Function): void {
const defineProperty = Object.defineProperty
Object.defineProperty = (o, p, d) => defineProperty(o, p, { ...(d || {}), configurable: false })
doSpying();
Object.defineProperty = defineProperty;
}
}
按如下方式调用
spyOnProperty
。
it('should call myFunction', () => {
JasminHelper.spyHack(() => {
spyOnProperty(FocusServiceSpy, 'myFunction', 'get');
});
expect(FocusServiceSpy.myFunction).toHaveBeenCalled();
});
基于Rudi的回答。