首页 > 解决方案 > 错误为无法读取属性“订阅”。在单元测试时以 7 角激活路线

问题描述

我收到错误,因为在单元测试时无法读取角度 7 中激活路由的未定义属性“订阅”。我已经以多种方式尝试过,请帮助。

Observer.of 不适合我,因为我有 rx.js 版本 6.3.3

这是我的组件文件 ChildComponent.ts

import { Component, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';

@Component({
    selector: 'app-child',
    template: `
        <h1>Enter your name</h1>
        <form
              [formGroup]="nameForm"
              (ngSubmit)="submitForm(nameForm)"
        >
            <input
                   type="text"
                   formControlName="firstName"
                   placeholder="first"
            >
            <input
                   type="text"
                   formControlName="lastName"
                   placeholder="last"
            >
            <button type="submit">launch to space</button>
        </form>
    `,
    styleUrls: ['./child.component.css']
})
export class ChildComponent {
    @Input() nameForm: FormGroup;
    private abc: number;
    constructor(
        public route: ActivatedRoute,
       ) {

        this.route.queryParams.subscribe(params => {
          this.abc = params['abc'];
        });

      }

    submitForm(form: FormGroup) {
        console.log(form);
        // really you would be using an event emitter
    }
}

这是我的子组件单元测试用例的单元测试文件


import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule, FormBuilder } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { ActivatedRoute, Router, Data, Params } from '@angular/router';
import { Observable, of } from 'rxjs';
import { BehaviorSubject } from 'rxjs';


export class MockActivatedRoute {
    private paramsSubject = new BehaviorSubject(this.testParams);
    private _testParams: {};

    params  = this.paramsSubject.asObservable();

    get testParams() {
        return this._testParams;
    }
    set testParams(newParams: any) {
        this._testParams = newParams;
        this.paramsSubject.next(newParams);
    }
}


import { ChildComponent } from './child.component';


describe('StaticComponent', () => {
    let component: ChildComponent;
    let fixture: ComponentFixture<ChildComponent>;

    class MockActivatedRoute1 extends ActivatedRoute {
    constructor() {
        super();
        this.params = of({id: "5"});
    }
  }

    // create new instance of FormBuilder
    const formBuilder: FormBuilder = new FormBuilder();
    let activeRoute: MockActivatedRoute;  


    beforeEach(() => {
        activeRoute = new MockActivatedRoute();
    });


    beforeEach(
        async(() => {
            TestBed.configureTestingModule({
                declarations: [
                    ChildComponent
                ],
                imports: [
                    CommonModule,
                    ReactiveFormsModule,
                    //AppModule
                ],
                providers: [
                    // reference the new instance of formBuilder from above
                    { provide: FormBuilder, useValue: formBuilder },
                    {
                        provide: ActivatedRoute,
                        useValue: {
                            params: {
                                subscribe: (fn: (value: Data) => void) => fn({
                                    abc: 1
                                })
                            }
                        }
                    }
                ]
            }).compileComponents();
        })
    );

    beforeEach(() => {
        fixture = TestBed.createComponent(ChildComponent);
        component = fixture.componentInstance;

        // pass in the form dynamically
        component.nameForm = formBuilder.group({
            firstName: null,
            lastName: null
        });
        fixture.detectChanges();
    });

    it('should be created', () => {
        expect(component).toBeTruthy();
    });
});

标签: angulartypescriptangular-unit-testangular-activatedroute

解决方案


你很亲近!为了让你的测试通过,我像这样模拟了 ActivatedRoute:

const mockActivatedRoute = { 
  queryParams: of({ abc: 'testABC' }) 
};

然后在 TestBed 的 providers 数组中使用它,如下所示:

providers: [
    ...
    { provide: ActivatedRoute, useValue: mockActivatedRoute }
]

这是一个有效的Stackblitz。在 Stackblitz 中,我还注释掉了所有其他不再需要的代码。


推荐阅读