我有一个使用浏览器的本机Blob
的打字稿模块。我想在节点中对其进行测试,因此我需要相同的模块来查看全局假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'});
}
}
现在我要像在
中那样在节点(而不是浏览器)中对其进行测试import { BlobMaker } from '../src/blob-maker';
import * as expect from 'expect';
describe('BlobMaker', () => {
it('makes a text blob', () => {
const blob = BlobMaker.makeTextBlob('foo');
expect(blob.getType()).equalTo('text/text');
});
});
由于Blob
在节点中不存在,因此无法编译。
显然我可以通过添加声明它存在吗?
export interface Global extends NodeJS.Global {
Blob: Blob;
}
但是我仍然需要在上面注入伪造的Blob
类,以便我正在测试的代码可以使用它。有办法做到这一点还是我应该以其他方式解决呢?
由于我需要Blob
的签名才能成为实际的本机浏览器makeTextBlob
,而不是某些自定义类型,因此我似乎无法将Blob
抽象到某种接口中。
我想我可以从测试中将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!
});
});
我收到一个错误,getType
上没有Blob
方法。我猜TS认为Blob
返回的BlobMaker.makeTextBlob
是本机的。我尝试过铸造
const blob = BlobMaker.makeTextBlob('foo') as Blob;
但它也不喜欢。
实际上,如果我可以将Blob
类注入node的全局名称空间中,这似乎将全部解决。那么,我该怎么做?
答案 0 :(得分:1)
这就是我解决的方法。希望它不是太可怕了
首先根据this Q&A,我可以通过添加单独的文件来扩展节点中的全局对象。就我而言,我制作了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
的部分移到另一个模块,但这至少建议一个解决方案。