如何在typescript中注入全局变量进行测试?
我有一个typescript模块,它使用浏览器的本机脚本。我想在节点中测试它,所以我需要相同的模块来查看全局伪如何在typescript中注入全局变量进行测试?,typescript,Typescript,我有一个typescript模块,它使用浏览器的本机脚本。我想在节点中测试它,所以我需要相同的模块来查看全局伪Blob实现。一个非常简单的假blob实现就可以了 class Blob { parts?: any; options?: any; constructor(parts: any, options?: any) { this.parts = parts; this.options = options; } getType():string {
Blob
实现。一个非常简单的假blob实现就可以了
class Blob {
parts?: any;
options?: any;
constructor(parts: any, options?: any) {
this.parts = parts;
this.options = options;
}
getType():string {
return options.type; // I know, hacky by just a demo
}
}
但如何将其注入节点的全局名称空间,以便通常在浏览器中运行的代码在节点中运行测试时能够看到它
换句话说,假设我有一个类,它将返回一个本机浏览器Blob
export class BlobMaker {
static makeTextBlob(text):Blob {
return new Blob([text], {type: 'text/text'});
}
}
现在我想在节点(而不是浏览器)中测试它,如中所示
这无法编译,因为节点中不存在Blob
显然,我可以通过添加来声明它的存在
export interface Global extends NodeJS.Global {
Blob: Blob;
}
但是我仍然需要在上面注入我的伪Blob
类,以便我正在测试的代码将使用它。有办法吗?或者我应该用其他方法来解决这个问题吗
似乎我无法将Blob
抽象为某种接口,因为我需要makeTextBlob
的签名作为实际的本机浏览器Blob
,而不是某种自定义类型
我想我可以通过一个Blob工厂从测试中深入到我的库中。路过一个深陷其中的工厂似乎有些过分。实际上我是通过打字来尝试的。我这样认为是因为它认为BlobMaker.makeBlob返回的类型不同
这是密码
let makeBlob = function(...args):Blob {
return new Blob(...args);
};
export function setMakeBlob(fn):void {
makeBlob = fn;
};
export class BlobMaker {
static makeTextBlob(text):Blob {
return makeBlob([text], {type: 'text/text'});
}
}
然后在测试中
import { BlobMaker, setMakeBlob } from '../src/blob-maker';
import { Blob } from "./fake-blob';
import * as expect from 'expect';
describe('BlobMaker', () => {
it('makes a text blob', () => {
setMakeBlob(function(parts, options) {
return new Blob();
});
const blob = BlobMaker.makeTextBlob('foo');
expect(blob.getType()).equalTo('text/text'); // ERROR!
});
});
我发现一个错误,Blob
上没有getType
方法。我猜TS认为BlobMaker.makeTextBlob
返回的Blob
是本地的。我试着投下它
const blob = BlobMaker.makeTextBlob('foo') as Blob;
但它也不喜欢这样
实际上,如果我可以将我的
Blob
类注入节点中的全局名称空间,这一切似乎都会得到解决。那么,我该怎么做呢?我就是这样解决的。希望不会太可怕
首先,我可以通过添加一个单独的文件来扩展节点中的全局对象。在我的例子中,我做了test.d.ts
并把它放进去
declare namespace NodeJS {
interface Global {
Blob: any
}
}
然后在我的测试中我做了这个
import { BlobMaker } from '../src/blob-maker';
import * as expect from 'expect';
class Blob {
parts?: any;
options?: any;
constructor(parts: any, options?: any) {
this.parts = parts;
this.options = options;
}
getType():string {
return options.type; // I know, hacky by just a demo
}
}
describe('BlobMaker', () => {
it('makes a text blob', () => {
global.Blob = Blob;
const blob = BlobMaker.makeTextBlob('foo');
expect(blob.getType()).equalTo('text/text');
});
});
它正在工作。我可能应该将正在修补
global.Blob
的部分移动到另一个模块,但它至少提出了一个解决方案。我的印象是///对不起,这是我第一次使用打字脚本,但这如何帮助Blob制作者找到Blob
?哦,等等,我误读了,你的Blob
是一个类,不是接口
(这应该意味着它在一个普通的.ts
文件中。你的BlobMaker
模块应该从“/Blob”
导入Blob,或者从任何导出它的地方导入Blob。即使它被理解为一个全局变量,在使用TypeScript时作为模块的一部分处理它要容易得多。我不确定这有什么帮助。这段代码仍然需要s在浏览器中运行并返回浏览器本地Blob
(更新了问题)。我只想在node中运行的测试中使用一个假blob来测试它。我自己还不是特别精通TypeScript,但从这里的上下文来看,我认为您应该考虑模拟blob
模块。我发现这可能对您有用,也可能对您没有用处,但您可以做的是重写blob
要处理的文件只有在global.Blob
上没有定义的情况下,才能使用global.Blob
。这样做是有效的,但为了确保它不会潜在地干扰其他测试,我会通过重写descripe('BlobMaker',()=>{const{Blob}=global;beforeach(()=>{global.Blob=require('./Blob');})更明确地说明模拟;afterEach(()=>{global.Blob=Blob;});it(…);});
import { BlobMaker } from '../src/blob-maker';
import * as expect from 'expect';
class Blob {
parts?: any;
options?: any;
constructor(parts: any, options?: any) {
this.parts = parts;
this.options = options;
}
getType():string {
return options.type; // I know, hacky by just a demo
}
}
describe('BlobMaker', () => {
it('makes a text blob', () => {
global.Blob = Blob;
const blob = BlobMaker.makeTextBlob('foo');
expect(blob.getType()).equalTo('text/text');
});
});