3

我有一个config.ts将与节点一起运行的 TypeScript 文件:

import myDependency = require('my-dependency');    

export = {
    doSomething = () => {
        ...
    }
}

在其他 TypeScript 文件中,我可以import使用完全类型安全的文件:

import config = require('./config');
config.doSomething();
config.doSomethingElse(); // compiler error, this method doesn't exist

现在我想对这个脚本进行单元测试。为了模拟这个脚本require()的依赖关系,我正在使用proxyquire,它让我可以提供我的脚本在调用require(). 这是我的测试可能的样子:

import proxyquire = require('proxyquire');
const config = proxyquire('./config', {
    'my-dependency': {} // this mocked object will be provided when config.ts asks for `my-dependency`
});

expect(config.doSomething()).to.do.something();

这很好用,除了我的config变量是类型的any,因为我使用proxyquire()的是require(). TypeScript 必须对require()函数进行特殊处理以允许它执行模块解析。有没有办法告诉 TypeScript 编译器也proxyquire()应该进行模块解析,类似于require()

我可以重写config.ts为一个类或让它使用一个接口。然后,我将能够通过导入类/接口定义在我的测试中显式键入变量。但是允许proxyquire()为我隐式输入内容将是更容易的解决方案。

4

1 回答 1

1

有一种解决方法 - 您可以config.ts通过导入实际模块并typeof在类型转换中使用来获取模块的类型:

import proxyquire = require('proxyquire');

import configType = require('./config');

const config = <typeof configType> proxyquire('./config', {
    'my-dependency': {} // this mocked object will be provided when config.ts asks for `my-dependency`
});

config.doSomething();

// config.noSuchMethod(); // does not compile

这并不理想,因为您必须在测试中导入相同的模块两次 - 真正的模块只是为了获得它的类型和“proxiquired”的模块以便在您的测试中实际使用,并且您必须小心不要混淆他们俩。但与为打字稿实现另一种模块解析变体的任务相比,它非常简单。此外,当 configType 以这种方式使用时——仅用于输入——它的导入甚至不会出现在生成的 javacsript 代码中。

于 2016-10-20T21:50:53.257 回答