How to unit test a component that depends on param

2019-01-16 12:30发布

I am unit testing a component that is used to edit an object. The object has an unique id that is used in order to grab the specific object from an array of objects that are hosted in a service. The specific idis procured through a parameter that is passed via routing, specifically through the ActivatedRoute class.

The constructor is as follows:

 constructor(private _router:Router, private _curRoute:ActivatedRoute, private _session:Session) {
}

ngOnInit() {
    this._curRoute.params.subscribe(params => {
        this.userId = params['id'];
        this.userObj = this._session.allUsers.filter(user => user.id.toString() === this.userId.toString())[0];

I want to run basic unit tests on this component. However, I am not sure as to how I can inject the id parameter, and the component needs this parameter.

By the way: I already have a mock for the Session service, so no worries there.

4条回答
趁早两清
2楼-- · 2019-01-16 12:44

I have figured out how to do this!

Since ActivatedRoute is a service, a mock service for it can be established. Let's call this mock service MockActivatedRoute. We will extend ActivatedRoute in MockActivatedRoute, as follows:

class MockActivatedRoute extends ActivatedRoute {
    constructor() {
        super(null, null, null, null, null);
        this.params = Observable.of({id: "5"});
    }

The line super(null, ....) initializes the super class, which has four mandatory parameters. However, in this instance, we need nothing from any of these parameters, so we initialize them to null values. All we need is the value of params which is an Observable<>. Therefore, with this.params, we override the value of params and initialize it to be the Observable<> of the parameter on which the test subject is relying.

Then, as any other mock service, just initialize it and override the provider for the component.

Good luck!

查看更多
戒情不戒烟
3楼-- · 2019-01-16 12:45

Just add a mock of the ActivatedRoute:

providers: [
  { provide: ActivatedRoute, useClass: MockActivatedRoute }
]

...

class MockActivatedRoute {
  // here you can add your mock objects, like snapshot or parent or whatever
  // example:
  parent = {
    snapshot: {data: {title: 'myTitle ' } },
    routeConfig: { children: { filter: () => {} } }
  };
}
查看更多
Root(大扎)
4楼-- · 2019-01-16 12:49

Here is how I tested it in angular 2.0 latest...

import { ActivatedRoute, Data } from '@angular/router';

and in Providers section

{
        provide: ActivatedRoute,
        useValue: {
          data: {
            subscribe: (fn: (value: Data) => void) => fn({
              yourData: 'yolo'
            })
          }
        }
      }
查看更多
够拽才男人
5楼-- · 2019-01-16 13:00

The simplest way to do this is to just use the useValue attribute and provide an Observable of the value you want to mock.

{
  provide: ActivatedRoute,
  useValue: {
    params: Observable.of({id: 123})
  }
}
查看更多
登录 后发表回答