带观众的模拟角路由器

时间:2019-12-06 21:16:26

标签: angular jestjs karma-jasmine ngmock angular-spectator

我正在使用Spectator编写Angular 8测试,并使用Jest运行它们。我是前端单元测试的新手,所以我可能忽略了一些简单的事情。任何想法都欢迎。

我有以下方法(在Typescript中),该方法根据当前URL是否匹配一组路径(不包括queryParam和片段),返回一个布尔值:

// custom-breadcrumb.component.ts

private blacklistedPaths: string[] = [''];

constructor(private router: Router) {
}

hideBreadcrumb(): boolean {
    let primaryUrlSegmentGroup: UrlSegmentGroup = this.router.parseUrl(this.router.url).root.children['primary'];
    if(primaryUrlSegmentGroup == null){
        return true;
    }
    let urlPath = primaryUrlSegmentGroup.segments.map((segment: UrlSegment) => segment.path).join('/');
    return this.blacklistedPaths.some((path: string) => path === urlPath);
}

// custom-breadcrumb.component.html

<xng-breadcrumb [hidden]="hideBreadcrumb()">
    <ng-container *xngBreadcrumbItem="let breadcrumb">
        ...
    </ng-container>
</xng-breadcrumb>

我现在想用Spectator编写测试,该测试将基于几个可能的URL验证布尔值返回值。在Java中,我将使用模拟对象模拟Router并执行以下操作:

when(mockObject.performMethod()).thenReturn(myReturnValue);

如何为Router创建模拟?以及如何定义this.router.parseUrl(this.router.url).root.children['primary']的返回值?

这是我目前拥有的:

// custom-breadcrumb.component.spec.ts

import {SpectatorRouting, createRoutingFactory} from '@ngneat/spectator/jest';

describe('CustomBreadcrumbComponent', () => {
    let spectator: SpectatorRouting<CustomBreadcrumbComponent>;
    const createComponent = createRoutingFactory({
        component: CustomBreadcrumbComponent,
        declarations: [
            MockComponent(BreadcrumbComponent),
            MockPipe(CapitalizePipe)
        ],
        routes: [{path: ''}]  // I don't think this works
    });

    beforeEach(() => spectator = createComponent());

    it('hideBreadcrumb - hide on homepage', () => {
        // TODO set url path to ''
        expect(spectator.component.hideBreadcrumb()).toBeTruthy();
    });

    it('hideBreadcrumb - show on a page other than homepage', () => {
        //TODO set url path to 'test' for example
        expect(spectator.component.hideBreadcrumb()).toBeFalsy();
    });
});

我知道createRoutingFactory是开箱即用的ActivatedRouteStub,但我无法对此做任何有意义的事情。

PS:我添加了业力作为标签,因为它可能具有相同的解决方案,但是如果我做错了,请纠正我。

1 个答案:

答案 0 :(得分:1)

给我的印象是spectator.router给了我一个模拟,而我不得不使用spectator.get<Router>(Router)来获得它。我遇到的另一个问题是html模板中的hideBreadcrumb方法是在组件创建时加载的,而我还没有机会模拟Router。这是我解决的方法:

detectChanges设置为false可以防止在创建观众组件时像这样加载html模板和ngOnInit:

let spectator: SpectatorRouting<CustomBreadcrumbComponent>;
const createComponent = createRoutingFactory({
    detectChanges: false,
    component: CustomBreadcrumbComponent,
    declarations: [ ... ]
});

beforeEach(() => {
    spectator = createComponent()
});

现在它不会调用hideBreadcrumb(),这可以成功创建旁观者。

我的测试是这样

it('hideBreadcrumb - hide on homepage', () => {
    let routerMock = spectator.get<Router>(Router);
    routerMock.parseUrl.andReturn({root: {children: {'primary': {segments: [{path: ''}]}}}});
    spectator.detectChanges();

    expect(spectator.component.hideBreadcrumb()).toBeTruthy();
});

我使用spectator.get<Router>(Router)从旁观者那里检索了一个模拟,并模拟了parseUrl方法的返回值。现在,我通过设置ngOnInit来允许html模板和spectator.detectChanges()进度。