【问题标题】:Can't resolve all parameters for Router: (?, ?, ?, ?, ?, ?, ?) in Angular RC 5 when unit testing单元测试时,Angular RC 5 中无法解析路由器的所有参数:(?, ?, ?, ?, ?, ?, ?)
【发布时间】: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)

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

【问题讨论】:

标签: javascript unit-testing angular typescript angular2-routing


【解决方案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 是现在的官方方式。
  • stackoverflow.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');
        });
        

        【讨论】:

          猜你喜欢
          • 2017-02-11
          • 2018-01-07
          • 2017-03-27
          • 2017-11-13
          • 2016-11-18
          • 1970-01-01
          • 2018-06-12
          • 2017-11-20
          • 1970-01-01
          相关资源
          最近更新 更多