测试 - 无法解析(ClassName)的所有参数

Sup*_*miu 17 karma-jasmine angular2-services angular2-injection angular2-testing angular

上下文

我创建了一个ApiService类来处理我们的自定义API查询,同时使用我们自己的序列化程序+其他功能.

ApiService的构造函数签名是:

constructor(metaManager: MetaManager, connector: ApiConnectorService, eventDispatcher: EventDispatcher);
Run Code Online (Sandbox Code Playgroud)
  • MetaManager 是一种处理api的metadatas的可注射服务.
  • ApiConnectorService是一个包装的服务,Http用于添加我们的自定义标题和签名系统.
  • EventDispatcher 基本上是Symfony的事件调度系统,在打字稿中.

问题

当我测试时ApiService,我做了一个初始化beforeEach:

beforeEach(async(() => {
    TestBed.configureTestingModule({
        imports  : [
            HttpModule
        ],
        providers: [
            ApiConnectorService,
            ApiService,
            MetaManager,
            EventDispatcher,
            OFF_LOGGER_PROVIDERS
        ]
    });
}));
Run Code Online (Sandbox Code Playgroud)

它工作正常.

然后,添加我的第二个规范文件,该文件是ApiConnectorService,与此beforeEach:

beforeEach(async(() => {
    TestBed.configureTestingModule({
        imports  : [HttpModule],
        providers: [
            ApiConnectorService,
            OFF_LOGGER_PROVIDERS,
            AuthenticationManager,
            EventDispatcher
        ]
    });
}));
Run Code Online (Sandbox Code Playgroud)

并且所有测试都因此错误而失败:

错误:无法解析ApiService的所有参数:(MetaManager,?,EventDispatcher).

  • 如果我从加载的测试中删除api-connector-service.spec.ts(ApiConnectorService的spec文件),ApiService测试将成功.
  • 如果我从加载的测试中删除api-service.spec.ts(ApiService的spec文件),ApiConnectorService测试将成功.

为什么我有这个错误?看起来我的两个文件之间的上下文存在冲突,我不知道为什么以及如何解决这个问题.

Mik*_*ple 20

使用玩笑?

如果有人来到这里并且您正在使用 Jest 来测试您的 Angular 应用程序(希望我们是一个不断增长的少数人),如果您没有发出装饰器,您将遇到此错误。您需要更新您的tsconfig.spec.json文件,使其看起来像:

{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "outDir": "../../out-tsc/spec",
    "types": [
      "jest",
      "node"
    ]
  },
  "files": [
  ],
  "include": [
    "**/*.spec.ts",
    "**/*.d.ts"
  ]
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢。错误消息中没有任何内容可以帮助解决这个问题。关键是“emitDecoratorMetadata”:true (3认同)

Pau*_*tha 16

这是因为在测试环境中Http无法从服务中解析服务HttpModule.它取决于平台浏览器.在测试过程中,您甚至不应该尝试进行XHR调用.

出于这个原因,Angular提供了一个MockBackendHttp服务使用的服务.我们使用这个模拟后端在我们的测试中订阅连接,并且我们可以在建立每个连接时模拟响应.

这是一个可以解决的简短完整示例

import { Injectable } from '@angular/core';
import { async, inject, TestBed } from '@angular/core/testing';
import { MockBackend, MockConnection } from '@angular/http/testing';
import {
  Http, HttpModule, XHRBackend, ResponseOptions,
  Response, BaseRequestOptions
} from '@angular/http';

@Injectable()
class SomeService {
  constructor(private _http: Http) {}

  getSomething(url) {
	return this._http.get(url).map(res => res.text());
  }
}

describe('service: SomeService', () => {
  beforeEach(() => {
	TestBed.configureTestingModule({
	  providers: [
		{
		  provide: Http, useFactory: (backend, options) => {
			return new Http(backend, options);
		  },
		  deps: [MockBackend, BaseRequestOptions]
		},
		MockBackend,
		BaseRequestOptions,
		SomeService
	  ]
	});
  });

  it('should get value',
	async(inject([SomeService, MockBackend],
				 (service: SomeService, backend: MockBackend) => {

	backend.connections.subscribe((conn: MockConnection) => {
	  const options: ResponseOptions = new ResponseOptions({body: 'hello'});
	  conn.mockRespond(new Response(options));
	});

	service.getSomething('http://dummy.com').subscribe(res => {
	  console.log('subcription called');
	  expect(res).toEqual('hello');
	});
  })));
});
Run Code Online (Sandbox Code Playgroud)

  • 据我所知,Angular.io上的文档也显示了很长的路要走.你的答案很好.只是想指出来.我见过许多例子,人们使用太复杂的配置然后抱怨DI很麻烦;-) (2认同)

Kes*_*ion 7

在选择的答案中并没有真正解决问题,这实际上只是编写测试的建议,而在注释中,您必须点击链接并在此处搜索。由于我又遇到了同样的错误,因此我将在此处添加两个解决方案。

  1. 解决OP问题的方法:

如果您有一个桶(index.ts或多个导出文件),如下所示:

export * from 'my.component' // using my.service via DI
export * from 'my.service'
Run Code Online (Sandbox Code Playgroud)

然后您可能会收到类似的错误EXCEPTION: Can't resolve all parameters for MyComponent: (?)

要修复它,您必须在组件之前导出服务:

export * from 'my.service'
export * from 'my.component' // using my.service via DI
Run Code Online (Sandbox Code Playgroud)
  1. 解决我的问题的方法:

由于circular dependency导致undefined服务导入的相同错误可能发生。console.log(YourService)导入后进行检查(在测试文件中-发生问题的位置)。如果未定义,您可能已经制作了一个index.ts文件(桶式),用于导出服务和使用该文件的文件(组件/效果/无论您要测试的内容)-通过从导出了索引的文件中导入服务(使其变成完整圆圈)。

找到该文件,然后直接从your.service.ts文件而不是从索引导入所需的服务。

  • 这个答案挽救了生命,谢谢! (2认同)