Как издеваться над NavParams в тестах?

Это может быть только вопрос Ionic 2, так как я не вижу NavParams в документах Angular 2, но некоторые концепции могут переводиться, поэтому я отметил оба.

Учитывая, что я звоню navparams.get('somekey') чтобы прослушивать передаваемые параметры, сложно насмехаться над NavParams в тестах.

Например, вот как я сейчас это делаю:

export class NavParamsMock {
  public get(key): any {
    return String(key) + 'Output';
  }
}

Это работает для действительно базовых тестов, но что, если у меня есть компонент, который я должен проверить, что это gets определенный тип Objectнапример, User,

Тогда я могу сделать что-то вроде

export class NavParamsMock {
  public get(key): any {
    if (key === 'user') {
       return new User({'name':'Bob'})
    }
    return String(key) + 'Output';
  }
}

Но это не работает, если вы хотите использовать get(user) в другом тесте или даже в спецификации другого компонента. Допустим, вы используете NavParams в 2 разных компонентах, и они оба ожидают разного результата, когда вы делаете get(user), становится все сложнее издеваться.

Кто-нибудь нашел решение по этому сценарию?

4 ответа

Решение

Вы можете получить значение по вашему выбору, реализовав свой собственный метод установки.

export class NavParamsMock {
  static returnParam = null;
  public get(key): any {
    if (NavParamsMock.returnParam) {
       return NavParamsMock.returnParam
    }
    return 'default';
  }
  static setParams(value){
    NavParamsMock.returnParam = value;
  }
}

Затем в каждом тесте вы можете получить доступ к сервису и установить свой собственный объект params.

beforeEach(() => {
  NavParamsMock.setParams(ownParams); //set your own params here
  TestBed.configureTestingModule({
    providers: [
      {provide: NavParams, useClass: NavParamsMock},
    ]
  });
})

Вместо того, чтобы издеваться над классом, проще всего создать экземпляр NavParams класс, а затем использовать его. NavParams делает data свойство публично присваивается, поэтому его можно изменять в каждом тесте по мере необходимости.

В приведенном ниже примере предполагается, что ваша страница выглядит примерно так:

@IonicPage()
@Component({...})
export class YourPage {
  private data: string;

  constructor(navParams: NavParams) {
    this.data = navParams.get('data');
  }
}

То есть ты звонишь navParams.get() на вашей странице constructor, ionViewDidLoad(), ngOnInit()или аналогичная функция инициализатора. В этом случае, чтобы изменить NavParams данные и убедитесь, что он используется правильно, вам нужно изменить введенный тест navParams.data собственности, а затем восстановить свою страницу:

import {IonicModule, NavParams} from 'ionic-angular';
import {ComponentFixture, TestBed} from '@angular/core/testing';

describe('YourPage', () => {
  let fixture: ComponentFixture<YourPage>;
  let component: YourPage;
  const data = {data: 'foo'};
  const navParams = new NavParams(data);

  function generateFixture() {
    fixture = TestBed.createComponent(YourPage);
    component = fixture.componentInstance;
    fixture.detectChanges();
  }

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [YourPage],
      imports: [
        IonicModule.forRoot(YourPage),
      ],
      providers: [
        {provide: NavParams, useValue: navParams},
      ]
    });
    generateFixture();
  });

  describe('NavParams', () => {
    it('should use injected data', () => {
      expect(component['data']).toEqual('foo');
    });
    it('should use new injected data', () => {
      const newData = {data: 'bar'};
      navParams.data = newData;
      generateFixture();
      expect(component['data']).toEqual('bar');
    });
  });
});

Если ваша страница звонит navParams.get('key') везде вместо назначения частному члену, а затем просто переназначения navParams.data свойство достаточно в каждом тесте (не нужно вызывать generateFixture() каждый раз).

Я изменил ответ @raj своим собственным вариантом этой техники. @raj's позволяет вам установить только один параметр. Мой позволяет хранить ключевые значения с несколькими параметрами.

export class NavParamsMock {
  static returnParams: any = {};

  public get(key): any {
    if (NavParamsMock.returnParams[key]) {
       return NavParamsMock.returnParams[key];
    }
    return 'No Params of ' + key + ' was supplied. Use NavParamsMock.setParams('+ key + ',value) to set it.';
  }

  static setParams(key,value){
    NavParamsMock.returnParams[key] = value;
  }
}

Вот пример с несколькими параметрами

NavParamsMock

export class NavParamsMock {

  static returnParams: any = {}

  public get (key): any {
    if (NavParamsMock.returnParams[key]) {
      return NavParamsMock.returnParams[key]
    }
  }

  static setParams (key, value): any {
    NavParamsMock.returnParams[key] = value
  }

}

Добавьте к провайдерам TestBed следующее

{provide: NavParams, useClass: NavParamsMock}

Модульный тест

it('i am a unit test', () => {
    const navParams = fixture.debugElement.injector.get(NavParams)

    navParams.get =
      jasmine
        .createSpy('get')
        .and
        .callFake((param) => {
          const params = {
            'param1': 'value',
            'param2':  'value'
          }
          return params[param]
        })


    comp.ionViewDidLoad()
  })
Другие вопросы по тегам