【问题标题】:How to Unit Test Angular 2 routing params如何对 Angular 2 路由参数进行单元测试
【发布时间】:2017-06-22 11:25:55
【问题描述】:

假设我想简单地对一个组件进行单元测试,该组件采用从路由的一部分获取的参数。例如,我的组件的 ngOnInit 如下所示:

  ngOnInit() {
    this.route.parent.params.switchMap((params: Params) => this.service.getProject(params['projectId']))
      .subscribe((project: Project) => this.update(project));
  }

我现在该怎么做: 1:设置我的测试,以便组件创建工作,所以我可以对其他部分进行单元测试

用答案编辑 - 示例 ActivatedRouteStub 应该扩展一个也有一个可观察参数的父级,我应该使用 useClass 而不是 useValue(忘记改回来):

@Injectable()
export class ActivatedRouteStub {

    // ActivatedRoute.params is Observable
    private subject = new BehaviorSubject(this.testParams);
    params = this.subject.asObservable();

    // Test parameters
    private _testParams: {};
    get testParams() { return this._testParams; }
    set testParams(params: {}) {
        this._testParams = params;
        this.subject.next(params);
    }

    // ActivatedRoute.snapshot.params
    get snapshot() {
        return { params: this.testParams };
    }
        // ActivatedRoute.parent.params
    get parent() {
        return { params: this.subject.asObservable() };
    }
}

2:在我的 UnitTest 中为 projectId 提供一个值?

angular2 文档中的示例似乎不适用于 switchMap,甚至根本不起作用(我从那里使用了 ActivatedRouteStub,但到目前为止没有运气 - 参数始终未定义)。

已编辑答案:

describe('ProjectDetailsComponent', () => {
  let component: ProjectDetailsComponent;
  let fixture: ComponentFixture<ProjectDetailsComponent>;
  let activatedRoute: ActivatedRouteStub;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule.withRoutes([{ path: 'projects/:projectId', component: ProjectDetailsComponent }])],
      declarations: [ProjectDetailsComponent],
      schemas: [NO_ERRORS_SCHEMA],
      providers: [{ provide: ProjectsService, useClass: ProjectsServiceStub }, {provide: ActivatedRoute, useClass: ActivatedRouteStub}]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(ProjectDetailsComponent);
    component = fixture.componentInstance;
    activatedRoute = fixture.debugElement.injector.get(ActivatedRoute);
    activatedRoute.testParams = { projectId: '123'};
    fixture.detectChanges();
  });

  fit('should create', () => {
    expect(component).toBeTruthy();
  });
});

【问题讨论】:

标签: angular angular2-routing angular2-testing


【解决方案1】:

params 未定义的唯一方法是您没有正确创建存根。看电话

this.route.parent.params.switchMap

params 是两层深的嵌套属性。所以作为普通的 JS 对象,你需要

let mock = {
  parent: {
    params: Observable.of(...)
  }
}

如果你想使用一个类,你可以使用类似的东西

class ActivatedRouteStub {

  parent = {
    params: Observable.of({})
  };

  set testParams(params: any) {
    this.parent.params = Observable.of(params);
  }
}

您只需在testParams 上使用setter 来设置parent.params 的值。那么当你执行stub.testParams = whatever 时,该值将设置在parent.params 的可观察对象上。

更新

除了上面关于如何实现这一点的解释之外,您的配置中也有错误

{provide: ActivatedRoute, useValue: ActivatedRouteStub}

useValue 应该是您创建的对象。因此,您正在传递一个类,该类将被注入,而不是该类的 instance。如果你想让 Angular 创建它,那么你应该使用useClass。否则,您应该自己创建实例,并将该实例用作值

{provide: ActivatedRoute, useValue: new ActivatedRouteStub() }

注意实例化。

【讨论】:

  • 当门铃响起时,我只是在输入这个作为我自己问题的答案,所以你得到了学分:D 我想通了。在我尝试了一切之后(到这点有半个周末......),我忘记将 useValue 改回 useClass。然后,意识到我应该能够在浏览器中调试这个测试(是的,我知道),我注意到父级不是可观察的。所以我更改了 ActivatedRouteStub 以返回相同的 testParams(稍后将更新测试以允许单独提供父参数)
  • 用答案更新了问题。当然,谢谢! new in useValue 也是一个有用的提示。
【解决方案2】:

如果有人最终在使用 Angular 7 时遇到了这个问题,Angular 文档给出了一个清晰的示例,说明如何测试依赖于 ActivatedRoute 服务的组件。请参阅:https://v7.angular.io/guide/testing#activatedroutestub。与上面的回答有点不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-16
    • 2017-08-08
    • 2017-02-09
    • 2018-01-05
    • 2019-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多