单元测试时,Angular RC 5 中无法解析路由器的所有参数:(?, ?, ?, ?, ?, ?, ?)

Posted

技术标签:

【中文标题】单元测试时,Angular RC 5 中无法解析路由器的所有参数:(?, ?, ?, ?, ?, ?, ?)【英文标题】:Can't resolve all parameters for Router: (?, ?, ?, ?, ?, ?, ?) in Angular RC 5 when unit testing 【发布时间】:2016-12-25 05:59:50 【问题描述】:

我刚刚升级到 Angular RC 5,现在所有使用“ROUTER_DIRECTIVES”的组件都失败了,当我尝试时“无法解析路由器的所有参数:(?, ?, ?, ?, ?, ?, ?)”对组件进行单元测试。

import  inject, addProviders  from '@angular/core/testing';
import  ComponentFixture, TestComponentBuilder  from '@angular/core/testing';
import  Component  from '@angular/core';
import  ROUTER_DIRECTIVES, Router  from '@angular/router';

import  HomeComponent  from './home.component';
import  UserService  from '../_services/user.service';

describe('Component: Home', () => 

  beforeEach(() => 
    addProviders([HomeComponent, UserService, ROUTER_DIRECTIVES, Router]);
  );  

  it('should inject the component', inject([HomeComponent, UserService, ROUTER_DIRECTIVES, Router],
    (component: HomeComponent) => 
      expect(component).toBeTruthy();
      // expect(component.currentUser.firstname).toEqual('Jan');
    ));

完整的错误日志:

     Chrome 52.0.2743 (Windows 10 0.0.0)
   Error: Can't resolve all parameters for Router: (?, ?, ?, ?, ?, ?, ?).
       at new BaseException (webpack:///C:/ng/anbud/~/@angular/compiler/src/facade/exceptions.js:27:0 <- src/test.ts:2943:23)
       at CompileMetadataResolver.getDependenciesMetadata (webpack:///C:/ng/anbud/~/@angular/compiler/src/metadata_resolver.js:551:0 <- src/test.ts:24542:19)
       at CompileMetadataResolver.getTypeMetadata (webpack:///C:/ng/anbud/~/@angular/compiler/src/metadata_resolver.js:448:0 <- src/test.ts:24439:26)
       at webpack:///C:/ng/anbud/~/@angular/compiler/src/metadata_resolver.js:594:0 <- src/test.ts:24585:41
       at Array.forEach (native)
       at CompileMetadataResolver.getProvidersMetadata (webpack:///C:/ng/anbud/~/@angular/compiler/src/metadata_resolver.js:575:0 <- src/test.ts:24566:19)
       at CompileMetadataResolver.getNgModuleMetadata (webpack:///C:/ng/anbud/~/@angular/compiler/src/metadata_resolver.js:305:0 <- src/test.ts:24296:58)
       at RuntimeCompiler._compileComponents (webpack:///C:/ng/anbud/~/@angular/compiler/src/runtime_compiler.js:150:0 <- src/test.ts:37986:47)
       at RuntimeCompiler._compileModuleAndAllComponents (webpack:///C:/ng/anbud/~/@angular/compiler/src/runtime_compiler.js:78:0 <- src/test.ts:37914:37)
       at RuntimeCompiler.compileModuleAndAllComponentsSync (webpack:///C:/ng/anbud/~/@angular/compiler/src/runtime_compiler.js:52:0 <- src/test.ts:37888:21)

任何想法如何使用路由对组件进行单元测试?

【问题讨论】:

我猜你需要像github.com/angular/angular/blob/…这样的东西 【参考方案1】:

终于可以修好了,就这么简单:

beforeEach(() => addProviders([
     
        provide: Router, 
        useClass: class  navigate = jasmine.createSpy("navigate"); 
    ]));

【讨论】:

从这里您可以使用 jasmine 进行测试。 expect(router.navigate).toHaveBeenCalledWith(['/success']); 在 2.0.0 中,将其添加到 NgModule 的提供程序部分时也可以使用:providers: [ provide: Router, useClass: class navigate = jasmine.createSpy("navigate"); ] 请更新您的答案,它已经过时了。 RouterTestingModule 是现在的官方方式。 ***.com/a/49407245/6017500 适用于最新版本的 Angular 7【参考方案2】:

对我来说,添加 RouterTestingModule 很有效

  import  RouterTestingModule  from '@angular/router/testing';

  beforeEach(async(() => 
    TestBed.configureTestingModule(
      imports: [
        RouterTestingModule
      ],
      declarations: [ HomeComponent ]
    )
    .compileComponents();
  ));

【讨论】:

【参考方案3】:

在我的例子中,我在提供者中有 Router,在导入中有 RouterTestingModule。猜猜这是引起冲突的原因。以下配置有效:

    TestBed.configureTestingModule(
        declarations: [Component],
        imports: [
            RouterTestingModule,             
        ],
        providers: [
         ...         //Remove Router from providers
        ]              

    );

【讨论】:

【参考方案4】:

我对上述解决方案没有任何运气。相反,我遵循了官方文档中推荐的方法:Testing Routed Components

首先,使用组件调用的任何方法创建一个存根路由器:

class RouterStub 
  navigateByUrl(url: string) 
    return url;
  

然后,在配置测试模块时,请执行以下操作:

TestBed.configureTestingModule(
  declarations: [HeaderComponent],
  providers: [
    provide: Router, useClass: RouterStub
  ]
);

【讨论】:

这对我来说是正确的答案。我只是把provide:Router,useClass:RouterStub放到了“providers”数组中,还把上面提到的“class RouterStub”(整个东西,连同body)直接放到了我的spec.ts文件中,报错是固定的。其他答案对我不起作用。【参考方案5】:

尝试添加RouterModule:

import  ROUTER_DIRECTIVES, Router, RouterModule  from '@angular/router';

beforeEach(() => 
        TestBed.configureTestingModule(
            providers: [
                 ...
                provide: Router, useClass: RouterModule,
        );
    );

【讨论】:

对于某些组件,使用此方法会导致错误“无法实例化循环依赖!Router ("[ERROR ->]"): in NgModule DynamicTestModule in ./DynamicTestModule@-1:-1” ?但是,使用@masterwok 的方法是有效的。【参考方案6】:

我只需要从提供商处移除路由器。这就是我的问题所在。

【讨论】:

就是这样。谢谢一百万【参考方案7】:

我遇到了同样的错误,在我的导入数组中导入 RouterTestModule,从提供程序中删除 Router/ActivatedRoute 并从我的导入数组中删除 RouterModule 帮助我解决了这个问题。

这就是我的工作版本的样子

import  RouterTestingModule  from '@angular/router/testing';
import  async, ComponentFixture, TestBed  from '@angular/core/testing';
import  FormsModule  from '@angular/forms';
import  MyAppComponent  from './my-apppp.component';
import  MyAppService  from '../../../services/my-app.service';
import  NO_ERRORS_SCHEMA from '@angular/core';

 beforeEach(async(() => 
    TestBed.configureTestingModule(
      declarations: [ MyAppComponent ],
      schemas:      [NO_ERRORS_SCHEMA],
      imports: [ FormsModule, RouterTestingModule ],
      providers: [ MyAppService ]
    )
    .compileComponents();
  ));

我知道很多人已经在这里发表了评论,但我觉得提供更新的答案会有所帮助。

谢谢!

【讨论】:

【参考方案8】:

对于最新的 Angular 7,这是对我有用的解决方案。 该示例复制自latest angular docs。

app/dashboard/dashboard.component.spec.ts(间谍)

const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']);
const heroServiceSpy = jasmine.createSpyObj('HeroService', ['getHeroes']);

TestBed.configureTestingModule(
  providers: [
     provide: HeroService, useValue: heroServiceSpy ,
     provide: Router,      useValue: routerSpy 
  ]
)

app/dashboard/dashboard.component.spec.ts(导航测试)

it('should tell ROUTER to navigate when hero clicked', () => 

  heroClick(); // trigger click on first inner <div class="hero">

  // args passed to router.navigateByUrl() spy
  const spy = router.navigateByUrl as jasmine.Spy;
  const navArgs = spy.calls.first().args[0];

  // expecting to navigate to id of the component's first hero
  const id = comp.heroes[0].id;
  expect(navArgs).toBe('/heroes/' + id,
    'should nav to HeroDetail for first hero');
);

【讨论】:

以上是关于单元测试时,Angular RC 5 中无法解析路由器的所有参数:(?, ?, ?, ?, ?, ?, ?)的主要内容,如果未能解决你的问题,请参考以下文章

如何对依赖于 RC3 路由器的组件进行单元测试?

Angular 2 RC 5 - 无法绑定到“...”,因为它不是“...”的已知属性

Angular 2 单元测试组件,模拟 ContentChildren

无法在 Angular 8 .net 核心中执行单元测试

更新gradle后Android单元测试无法解析被测类

无法使用 Angular 2 rc5 发出 http 请求