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

Posted

技术标签:

【中文标题】如何对依赖于 RC3 路由器的组件进行单元测试?【英文标题】:How can I unit test components that depend on the RC3 router? 【发布时间】:2016-11-03 14:46:45 【问题描述】:

我正在尝试获取与 RC1 一起使用“新新”路由器的单元测试。我怎样才能在3.0.0-alpha.8 上实现这一点?

我的依赖:

"@angular/common": "2.0.0-rc.3",
"@angular/compiler": "2.0.0-rc.3",
"@angular/core": "2.0.0-rc.3",
"@angular/forms": "0.2.0",
"@angular/platform-browser": "2.0.0-rc.3",
"@angular/platform-browser-dynamic": "2.0.0-rc.3",
"@angular/router": "3.0.0-beta.2",

我要测试的组件使用routerLink 指令:

import ROUTER_DIRECTIVES from '@angular/router';
@Component(
    selector: 'app-topmenu',
    template: require('./app-topmenu.tpl.html'),
    directives: [ROUTER_DIRECTIVES]
)
export class TopMenu 
<nav class="app-top-menu">
    <a *ngFor="let link of links" [routerLink]="link.route">link.text</a>
</nav>

以前,使用 rc1,我使用类似这样的东西来对我的组件进行单元测试:

import Location from '@angular/common';
import SpyLocation from '@angular/common/testing';
import Router, RouteRegistry, ROUTER_DIRECTIVES, ROUTER_PRIMARY_COMPONENT from '@angular/router-deprecated';
import RootRouter from '@angular/router-deprecated/src/router';

describe('Router link capabilities', () => 
    beforeEachProviders(() => [
        RouteRegistry,
         provide: Location, useClass: SpyLocation ,
         provide: ROUTER_PRIMARY_COMPONENT, useValue: TestComponent ,
         provide: Router, useClass: RootRouter 
    ]);

    it('creates routerLinks with the expected URLs', fakeAsync(
        inject([TestComponentBuilder, Location], (tcb: TestComponentBuilder, spyLocation: SpyLocation) => 
            tcb.overrideTemplate(TestComponent, `
                <app-top-menu [links]='[
                     text: "A", route: ["/TestA/TestB/TestC"] ,
                     text: "B", route: ["/TestA", "TestB", "TestC"] 
                ]'></app-top-menu>
                <router-outlet></router-outlet>
            `).createAsync(TestComponent)
            .then((fixture: ComponentFixture<TestComponent>) => 
                fixture.detectChanges();
                spyLocation.simulateUrlPop('url-a/url-b/url-c');
                tick();
                fixture.detectChanges();
                let nativeLinks: HTMLAnchorElement[] = fixture.nativeElement.querySelectorAll('a');

                expect(nativeLinks.length).toBe(2);
                expect(nativeLinks[0].textContent).toBe('A');
                expect(nativeLinks[1].textContent).toBe('B');
            );
        )
    ));
);

当我尝试将 routerLink 导入从 @angular/router-deprecated 切换到从 @angular/router 导入 ROUTER_DIRECTIVES 时,我收到一个错误:

ORIGINAL EXCEPTION: Platforms have to be created via `createPlatform`!

我可以在网上找到有关测试“新新”路由器的所有文档,createPlatform 消息指的是提供 ROUTER_FAKE_PROVIDERS,它似乎包含在 rc2 中,但随 rc3 一起消失了:

import ROUTER_FAKE_PROVIDERS from '@angular/router/testing';
// ^ [ts] Cannot find module '@angular/router/testing'.

node_modules/@angular/router文件夹中搜索编译的.d.ts文件,我也没有找到任何关于testing/mocks/fakes的引用。

有人迁移到 rc3 并开始工作了吗?

【问题讨论】:

看看这些测试github.com/angular/angular/blob/master/modules/%40angular/… 【参考方案1】:

要测试 RC3 (3.0.0-alpha.*) 路由器,您需要做一些与以前版本中路由器设置不同的事情。

您需要像这样定义RouterConfig

import provideRouter, RouterConfig from '@angular/router';

export const APP_ROUTES : RouterConfig = [
    path: '', component: AppComponent,
    // more paths
];

export const APP_ROUTE_PROVIDERS = [
    provideRouter(APP_ROUTES)  
];

然后在你的测试文件中

import ActivatedRoute, RouterConfig, Router from '@angular/router';

class MockRouter  createUrlTree()  
class MockActivatedRoute  

beforeEachProviders(() => [
  provide(Router,  useClass: MockRouter ),
  provide(ActivatedRoute,  useClass: MockActivatedRoute ),
]);

describe()
   // etc

您的路由器现在可以测试了。

对于 RC4:

import ActivatedRoute, RouterConfig, Router from '@angular/router';

class MockRouter  createUrlTree()  
class MockActivatedRoute  



describe()
  beforeEach(() => [
      addProviders([
          provide(Router,  useClass: MockRouter ),
          provide(ActivatedRoute,  useClass: MockActivatedRoute ),
      ]);
  ]);
  //etc

【讨论】:

但这并不能让我测试依赖于实际routerLink 功能的组件,是吗?我不想测试路由器,我想测试使用路由器的组件。请参阅第二段(现在为粗体)。这在之前使用SpyLocationMockLocationStrategy 是可能的,但MockLocationStrategy 不会在rc4 中导出。 所以你想测试当一个链接被点击时它会导航到正确的页面吗?如果是这样,您可以使用 SpyLocation 的isCurrentPathEqualTo(path: string, query: string = ''): boolean 方法。用JS模拟一个链接点击,然后用这个方法使用expect。我相信你认为这行不通是正确的。在工作中,我们在路由器周围有一个包装器,用于存储我们导航到的路由,因此我们测试该路由日志。 你如何用ActivatedRoute模拟路由参数?

以上是关于如何对依赖于 RC3 路由器的组件进行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中对依赖于 3rd-Party-Package 的代码进行单元测试?

如何用mockito+spring进行单元测试

使用 b 按钮“to”对 vue 路由进行单元测试

如何对第一个Vue.js组件进行单元测试 (上)

如何对包含Task.Delay的代码进行单元测试?

如何对 Joomla 2.5 组件进行单元测试