【问题标题】:Angular2 - mocking RouteParams in testAngular2 - 在测试中模拟 RouteParams
【发布时间】:2016-04-18 08:26:54
【问题描述】:

我在 Angular2 组件的测试中为 RouteParams 依赖项注入模拟时遇到了一些问题。我的一般想法是我可能缺少一些提供者。

测试失败:

无法解析“RouteParams”(?)的所有参数。确保所有参数都用 Inject 修饰 或具有有效的类型注释,并且“RouteParams”用 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');
  }));

});

【问题讨论】:

    标签: javascript unit-testing typescript angular angular2-routing


    【解决方案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');
      }));
    
    });
    

    【讨论】:

      【解决方案2】:

      适用于即使使用 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(),
        }
      ]
      

      为了完成,我在我正在测试的组件中使用它的方式:

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

      【讨论】:

        猜你喜欢
        • 2017-09-08
        • 2014-11-01
        • 2017-04-19
        • 1970-01-01
        • 2017-03-14
        • 1970-01-01
        • 2017-05-10
        • 1970-01-01
        • 2016-07-14
        相关资源
        最近更新 更多