Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/433.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用Angular2测试床模拟具有非具体类接口参数的服务_Javascript_Angular_Testbed - Fatal编程技术网

Javascript 使用Angular2测试床模拟具有非具体类接口参数的服务

Javascript 使用Angular2测试床模拟具有非具体类接口参数的服务,javascript,angular,testbed,Javascript,Angular,Testbed,我有一个组件,我正在尝试使用TestBed进行设置和测试 此组件包含一个类,该类的构造函数中有一个参数,该参数是接口,而不是具体的类。这个接口由我选择使用的任何类(真实类或用于单元测试的mok类)来满足。但是,当我在测试床中构建使用该服务的组件时,我不知道如何将该参数定义到测试床配置中 以下是组件的测试床配置: describe('PanelContentAreaComponent', () => { let component: PanelContentAreaComponent;

我有一个组件,我正在尝试使用TestBed进行设置和测试

此组件包含一个类,该类的构造函数中有一个参数,该参数是接口,而不是具体的类。这个接口由我选择使用的任何类(真实类或用于单元测试的mok类)来满足。但是,当我在测试床中构建使用该服务的组件时,我不知道如何将该参数定义到测试床配置中

以下是组件的测试床配置:

describe('PanelContentAreaComponent', () => {
  let component: PanelContentAreaComponent;
  let fixture: ComponentFixture<PanelContentAreaComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ PanelContentAreaComponent
          ],
      providers:[
        MenuCommandService, ProcedureDataService, IOpenService],
      schemas: [CUSTOM_ELEMENTS_SCHEMA]
    })
    .compileComponents();
  }));
ProcedureDataService
构造函数中的一个参数是
IOpenService
,其定义为:

export interface IOpenService {
    openFile(fileType: string, dataType: string, filePath: string) ;
}
正如您所看到的,这是一个接口,而不是一个具体的类

在我的服务单元测试中,我们通过如下方式实现IOpenService来模拟它:

export class mockOpenService implements IOpenService{

    constructor(){}

    openFile(fileType: string, dataType: string, filePath: string) {
        let fileContent: OpenFile;
... 
...
[fake the data with mok junk]
...
        fileContent = {
            'filePath': filePath,
            'fileName': name,
            'openSuccess': isSuccess,
            'error': errorMsg,
            'fileData': jsonData
        };

        return Observable.of(fileContent);

    }

}
这在ProcedureDataService服务单元测试中非常有效。当然,在实际代码中,我们使用完整实现的文件打开服务实现IOpenService,该服务可以正确获取数据

但在尝试在组件内部使用此服务时,我会遇到以下错误:

PanelContentAreaComponent should create FAILED
        Failed: IOpenService is not defined
        ReferenceError: IOpenService is not defined
这是有道理的,所以我试图弄清楚如何告诉测试床我有一个我希望使用的IOpense服务的具体类实现。我试过了,但失败了:

describe('PanelContentAreaComponent', () => {
  let component: PanelContentAreaComponent;
  let fixture: ComponentFixture<PanelContentAreaComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ PanelContentAreaComponent
          ],
      providers:[
        {provide: IOpenService, useClass: mockOpenService},
        MenuCommandService, ProcedureDataService, IOpenService],
      schemas: [CUSTOM_ELEMENTS_SCHEMA]
    })
    .compileComponents();
  }));
我仍然得到:

PanelContentAreaComponent should create FAILED
        Failed: IOpenService is not defined
        ReferenceError: IOpenService is not defined

那么,我如何指示
TestBed
我有一个接口参数(
IOpenService
)的特定类(
mockOpenService
)实现,该接口参数是为测试该组件(
PanelContentAreaComponent
)而提供的服务(
ProcedureDataService
)所需的?接口不能用作令牌。本章对此进行了解释

类型脚本接口不是有效的令牌

export interface AppConfig {
  apiEndpoint: string;
  title: string;
}

export const HERO_DI_CONFIG: AppConfig = {
  apiEndpoint: 'api.heroes.com',
  title: 'Dependency Injection'
};
HERO\u DI\u CONFIG
常量有一个接口,
AppConfig
。不幸的是,我们不能将TypeScript接口用作令牌:

// FAIL! Can't use interface as provider token
[{ provide: AppConfig, useValue: HERO_DI_CONFIG })]

// FAIL! Can't inject using the interface as the parameter type
constructor(private config: AppConfig){ }
如果我们习惯于强类型语言中的依赖项注入,而接口是首选的依赖项查找键,那么这似乎很奇怪

这不是安格尔的错。接口是TypeScript设计时工件。JavaScript没有接口。TypeScript接口从生成的JavaScript中消失。运行时,Angular无法找到任何接口类型信息

文档继续解释您应该创建一个
OpaqueToken

对于这个例子来说没关系,但在我们的服务案例中,这并不是最优雅的解决方案。就我个人而言,我认为更优雅的解决方案是完全不为服务使用接口。而是使用抽象类。抽象类被转换为实际代码,就像普通类一样。所以你可以用它作为代币

export abstract class IOpenService {
    abstract openFile(fileType: string, dataType: string, filePath: string): any ;
}

class OpenService extends IOpenService {
  openFile(fileType: string, dataType: string, filePath: string): any  {

  }
}
现在你可以做了

{ provide: IOpenService, useClass: OpenService }

接口不能用作令牌。本章对此进行了解释

类型脚本接口不是有效的令牌

export interface AppConfig {
  apiEndpoint: string;
  title: string;
}

export const HERO_DI_CONFIG: AppConfig = {
  apiEndpoint: 'api.heroes.com',
  title: 'Dependency Injection'
};
HERO\u DI\u CONFIG
常量有一个接口,
AppConfig
。不幸的是,我们不能将TypeScript接口用作令牌:

// FAIL! Can't use interface as provider token
[{ provide: AppConfig, useValue: HERO_DI_CONFIG })]

// FAIL! Can't inject using the interface as the parameter type
constructor(private config: AppConfig){ }
如果我们习惯于强类型语言中的依赖项注入,而接口是首选的依赖项查找键,那么这似乎很奇怪

这不是安格尔的错。接口是TypeScript设计时工件。JavaScript没有接口。TypeScript接口从生成的JavaScript中消失。运行时,Angular无法找到任何接口类型信息

文档继续解释您应该创建一个
OpaqueToken

对于这个例子来说没关系,但在我们的服务案例中,这并不是最优雅的解决方案。就我个人而言,我认为更优雅的解决方案是完全不为服务使用接口。而是使用抽象类。抽象类被转换为实际代码,就像普通类一样。所以你可以用它作为代币

export abstract class IOpenService {
    abstract openFile(fileType: string, dataType: string, filePath: string): any ;
}

class OpenService extends IOpenService {
  openFile(fileType: string, dataType: string, filePath: string): any  {

  }
}
现在你可以做了

{ provide: IOpenService, useClass: OpenService }

看起来你提供了两次“IOpense服务”?@vidalsason对。。。“descripe”的最后一段代码单独列出了
{provide:IOpenService,useClass:mockOpenService}、
IOpenService
。我想我在想可能需要这样做。但最初的一个只是
提供者:[MenuCommandService,ProcedureDataService,IOpenService],
。。但它们都失败了…看起来你提供了两次“IOpense服务”?@Vidalsason对。。。“descripe”的最后一段代码单独列出了
{provide:IOpenService,useClass:mockOpenService}、
IOpenService
。我想我在想可能需要这样做。但最初的一个只是
提供者:[MenuCommandService,ProcedureDataService,IOpenService],
。。但这两个都失败了……你的答案正好针对我遇到的另一个问题——不一定是关于模拟或单元测试。遗憾的是,接口不能用作提供者令牌。我真的希望能够在运行时注入具体的类来代替接口的使用。我尝试并放弃了OpaqueToken,因为它仍然迫使我在构造函数签名中指定注入关注点。我用一个具有完全抽象成员的抽象类替换了接口。这允许我使用app.module.ts中的提供者令牌在运行时注入我的具体类。向上投票,开始GSW!OpaqueToken已被弃用(看起来它也被删除了),您应该使用InjectionToken,而您的答案正好是针对我遇到的另一个问题—不一定是关于模拟或单元测试。遗憾的是,接口不能用作提供者令牌。我真的希望能够在运行时注入具体的类来代替接口的使用。我试着放弃了猫眼石