【问题标题】:AngularTesting Fails when adding Router provider添加路由器提供程序时AngularTesting失败
【发布时间】:2020-06-11 15:11:37
【问题描述】:

我有一个在主组件上调用的 Header 组件,这是因为我有一个 *ngIf 来检查我所在的路由并以不同的方式呈现标题。 代码工作正常,标题呈现不同,具体取决于我在应用程序上的位置。

我正在尝试根据我所在的路线测试标头。 如果我不接触代码,之前的测试通过,但是当我添加路由器提供程序时,所有测试都失败了。

只需添加提供者所有测试失败,我什至不需要添加我的新测试。

可能是什么原因?

import {async, ComponentFixture, TestBed} from "@angular/core/testing";
import {DatasetMainComponent} from "./dataset-main.component";
import {DatasetHeaderComponent} from "../dataset-header/dataset-header.component";
import {DatasetNavigationComponent} from "../dataset-navigation/dataset-navigation.component";
import {CustomMaterialModule} from "../../shared/customMaterial.module";
import {ActivatedRoute, Router} from "@angular/router";
import {ActivatedRouteStub} from "../../testing/activatedRouteStub";
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
import {RouterTestingModule} from "@angular/router/testing";
import {DatasetVersionService} from "../services/datasetVersion.service.interface";
import {MockDatasetServiceImpl} from "../utils/commonData.spec";
import {HttpClientModule} from "@angular/common/http";
import {Directive, Input, LOCALE_ID} from "@angular/core";
import {MatExpansionPanel} from "@angular/material/expansion";
import {By} from "@angular/platform-browser";
import {ErrorHandlingStubComponent} from "../../testing/error-handling-stub";
import {MatMenuItem} from "@angular/material/menu";
import {MetadataService} from "../../common-metadata/services/metadata.service.interface";
import {MockMetadataImplService} from "../../shared-study-metadata/utils/common-data.spec";
import {AppModule} from "../../app.module";
import {of} from "rxjs";
import {SharedModule} from "../../shared/shared.module";
import {PermissionDirective} from "../../core/utils/permission.directive";
import {ButtonComponent} from "../../shared/components";
import {RouterStub} from "../../testing/routerStub";
import {AuthorizationService, AuthService} from "../../core/services";
import {AuthImplService} from "../../core/services/authImpl.service";
import {MockAuthorizationService} from "../../core/specs/commonData.spec";

const activatedRoute = new ActivatedRouteStub();

@Directive({selector: "[appPermissions]"})
export class StubPermissionDirective {
    @Input() permissions: any[];
}

fdescribe("DatasetMainComponent", () => {
    let component: DatasetMainComponent;
    let componentFixture: ComponentFixture<DatasetMainComponent>;
    let element: any;
    let debugElement: any;
    let datasetVersionService: MockDatasetServiceImpl;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [
                DatasetMainComponent,
                DatasetHeaderComponent,
                DatasetNavigationComponent,
                ErrorHandlingStubComponent,
                StubPermissionDirective,
            ],
            imports: [
                AppModule,
                SharedModule,
                CustomMaterialModule,
                BrowserAnimationsModule,
                RouterTestingModule,
                HttpClientModule
            ],
            providers: [
                {provide: ActivatedRoute, useValue: activatedRoute},
                {provide: DatasetVersionService, useClass: MockDatasetServiceImpl},
                {provide: MetadataService, useClass: MockMetadataImplService},
                {provide: Router, useClass: RouterStub},
                {provide: AuthService, useClass: AuthImplService},
                {provide: AuthorizationService, useClass: MockAuthorizationService},
                {provide: LOCALE_ID, useValue: "en"},
            ]
        }).overrideModule(SharedModule, {
            remove: {
                exports: [PermissionDirective]
            }
        }).compileComponents().then(() => {
            activatedRoute.setParamMap({datasetVersionId: "1", datasetRefNumber: "1"});
            componentFixture = TestBed.createComponent(DatasetMainComponent);
            component = componentFixture.componentInstance;
            element = componentFixture.nativeElement;
            debugElement = componentFixture.debugElement;
        });

        datasetVersionService = TestBed.get(DatasetVersionService);
    }));

    it("Delete a dataset works", () => {
        componentFixture.detectChanges();
        spyOn(datasetVersionService, "deleteDatasetVersion").and.callThrough();
        spyOn(component.dialogController, "openSimpleDialog").and.returnValue(of(true));
        spyOn(component, "deleteDatasetVersion").and.callThrough();

        // Confirm deletion on DialogControllerStubComponent
        const buttons  = element.getElementsByTagName("button");
        buttons[2].click();
        componentFixture.detectChanges();

        // const menuItems = debugElement.queryAll(By.directive(MatMenuItem));
        const menuItems = debugElement.queryAll(By.directive(ButtonComponent));
        expect(menuItems.length).toBe(4);
        expect(menuItems[3].nativeElement.innerText).toBe("Delete");
        // Use component instance to get isDisabled property
        expect(menuItems[3].componentInstance.isDisabled).toBe(false);
        // app-button wraps a button with click function that triggers the event 'onclick'
        menuItems[3].query(By.css("button")).nativeElement.click();
        componentFixture.detectChanges();

        expect(component.deleteDatasetVersion).toHaveBeenCalled();
        expect(datasetVersionService.deleteDatasetVersion).toHaveBeenCalledWith(1);
    });

    it("navigation menu is shown correctly", () => {
        componentFixture.detectChanges();
        const panels = componentFixture.debugElement.queryAll(By.directive(MatExpansionPanel));
        expect(panels.length).toBe(2);  // Files is not a panel
        panels[0].triggerEventHandler("open", null);
        const links = element.getElementsByTagName("a");
        expect(links.length).toBe(7);  // Files is a link
        expect(links[0].innerText).toBe("Description");
        expect(links[1].innerText).toBe("Archiving");
        expect(links[2].innerText).toBe("Block 1 en");
        expect(links[3].innerText).toBe("Block 2 en");
        expect(links[4].innerText).toBe("Files");
        expect(links[5].innerText).toBe("Deposit contract");
        expect(links[6].innerText).toBe("User contract");
    });
    it("Update a dataset version works", () => {
        componentFixture.detectChanges();
        spyOn(component.dialogController, "openSimpleDialog").and.returnValue(of(true));
        spyOn(datasetVersionService, "updatePublishedDatasetVersion").and.callThrough();
        const buttons  = element.getElementsByTagName("button");
        buttons[1].click();
        componentFixture.detectChanges();
        expect(datasetVersionService.updatePublishedDatasetVersion).toHaveBeenCalledWith(1);
    });

    it("Only displays Title and ref on Catalogue Route", () => {
      const router = TestBed.get(Router);
      router.url = "/catalogue";
      componentFixture.detectChanges();
      const title = element.getElementsByTagName("sub-title-wrapper");
      console.log(title);
});
});

最后一个测试是我的新测试,我想检查是否在包装器中呈现了某些内容,但由于以下错误,我什至看不到日志:

  TypeError: Cannot read property 'subscribe' of undefined

添加此错误后,所有测试中都会出现此错误:

  {provide: Router, useClass: RouterStub},

【问题讨论】:

  • 你需要分享你写了.subscribe(的组件代码。您需要在RouterStub 中创建该方法

标签: angular testing karma-jasmine


【解决方案1】:

我没有检查Shashank解决方案,所以我无法确定是否可以解决问题。

我找到的解决方案是这样声明路由:

RouterTestingModule.withRoutes([
                    {path: "Machines", component: InfoPanelStubComponent},
                    {path: "Users", component: InfoPanelStubComponent}
                ])

然后使用导航访问:

const router = TestBed.get(Router);
router.navigate(["Machines"]);
flush();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-12
    • 2021-11-06
    • 2014-08-28
    • 1970-01-01
    • 2017-04-11
    • 2016-01-16
    • 1970-01-01
    相关资源
    最近更新 更多