簡體   English   中英

Angular2 - 在測試中模擬RouteParams

[英]Angular2 - mocking RouteParams in test

我在為Angular2組件的測試中為RouteParams依賴項注入模擬時遇到了一些麻煩。 我的一般想法是,我可能會錯過一些提供者。

測試失敗了:

Cannot resolve all parameters for 'RouteParams'(?). Make sure that all the parameters are decorated with Inject
or have valid type annotations and that 'RouteParams' is decorated with Injectable.

有誰知道問題可能是什么?

import {
  it,
  inject,
  injectAsync,
  describe,
  beforeEach,
  beforeEachProviders,
  TestComponentBuilder
} from 'angular2/testing';

import {Component, provide} from 'angular2/core';
import {BaseRequestOptions, Http} from 'angular2/http';
import {MockBackend} from 'angular2/http/testing';
import {RouteParams, ROUTER_PROVIDERS, ROUTER_PRIMARY_COMPONENT} from 'angular2/router';

// Load the implementations that should be tested
import {Home} from './home';
import {Title} from './providers/title';

describe('Home', () => {
  // provide our implementations or mocks to the dependency injector

  beforeEachProviders(() => [
    Title,
    Home,
    provide(RouteParams, { useValue: new RouteParams({ id: '1' }) }),
    BaseRequestOptions,
    MockBackend,
    provide(Http, {
        useFactory: function(backend, defaultOptions) {
            return new Http(backend, defaultOptions);
        },
        deps: [MockBackend, BaseRequestOptions]
    }),
    provide(RouteParams, {
        useFactory: function() {
            return new RouteParams({ 'id':'1' });
        }
    })
  ]);

  it('should have a title', inject([ Home ], (home) => {
    expect(home.title.value).toEqual('Angular 2');
  }));

  it('should have a http', inject([ Home ], (home) => {
    expect(!!home.http).toEqual(true);
  }));

  it('should log ngOnInit', inject([ Home ], (home) => {
    spyOn(console, 'log');
    spyOn(console, 'info');
    expect(console.log).not.toHaveBeenCalled();
    expect(console.info).not.toHaveBeenCalled();

    home.ngOnInit();
    expect(console.log).toHaveBeenCalled();
    expect(console.info).toHaveBeenCalledWith('1');
  }));

});

管理自己解決這個問題,你通過使用模擬RouteProvider

provide(RouteParams, { useValue: new RouteParams({ id: '1' }) })

import {
  it,
  inject,
  injectAsync,
  describe,
  beforeEach,
  beforeEachProviders,
  TestComponentBuilder
} from 'angular2/testing';

import {Component, provide} from 'angular2/core';
import {BaseRequestOptions, Http} from 'angular2/http';
import {MockBackend} from 'angular2/http/testing';
import {RouteParams, ROUTER_PROVIDERS, ROUTER_PRIMARY_COMPONENT} from 'angular2/router';

// Load the implementations that should be tested
import {Home} from './home';
import {Title} from './providers/title';

describe('Home', () => {
  // provide our implementations or mocks to the dependency injector

  beforeEachProviders(() => [
    Title,
    Home,
    provide(RouteParams, { useValue: new RouteParams({ id: '1' }) }),
    BaseRequestOptions,
    MockBackend,
    provide(Http, {
        useFactory: function(backend, defaultOptions) {
            return new Http(backend, defaultOptions);
        },
        deps: [MockBackend, BaseRequestOptions]
    })
  ]);

  it('should have a title', inject([ Home ], (home) => {
    expect(home.title.value).toEqual('Angular 2');
  }));

  it('should have a http', inject([ Home ], (home) => {
    expect(!!home.http).toEqual(true);
  }));

  it('should log ngOnInit', inject([ Home ], (home) => {
    spyOn(console, 'log');
    spyOn(console, 'info');
    expect(console.log).not.toHaveBeenCalled();
    expect(console.info).not.toHaveBeenCalled();

    home.ngOnInit();
    expect(console.log).toHaveBeenCalled();
    expect(console.info).toHaveBeenCalledWith('1');
  }));

});

對於那些在這里降落的人,即使他們正在使用Angular4

我只是繼續創造了一個模擬。 我想訣竅是模擬你需要的ActivatedRoute部分。 對我來說,這樣做了:

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

/**
 * Mocking the ActivatedRoute which is injected in the Component on creation.
 * This allows for easier testing as values can be set as needed.
 */
class MockActivatedRoute {
   paramMap = Observable.of(new Params());
}

/**
 * Bare bones implementation of ParamMap used in mock. Further tests can expand
 * on this implementation as needed.
 */
class Params implements ParamMap {
  keys: string[];

  private routes: {[key: string]: string|null} = {
    subject: 'foo',
    time: 'd-123-1',
    device: 'all',
    location: 'c-123'
  };

  constructor() {
    this.keys = Object.keys(this.routes);
  }

  has(name: string): boolean {
    throw new Error('Method not implemented.');
  }
  get(name: string): string|null {
    return this.routes[name];
  }
  getAll(name: string): string[] {
    throw new Error('Method not implemented.');
  }
}

然后在您的測試模塊中確保您通過真實的ActivatedRoute提供模擬服務:

providers: [
  {
    provide: ActivatedRoute,
    useValue: new MockActivatedRoute(),
  }
]

為了完成,我在組件I測試中使用它的方式:

ngOnInit() {
  this.route.paramMap
      .map((params: ParamMap) => params.get('subject') as string)
      .subscribe((subject: string) => this.subject = subject);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM