Jasmine Testing Constructor, который обещает

У меня есть служба, которая действует как хранилище данных. В своем конструкторе он пытается «увлажнить» набор данных из хранилища устройства (используя Ionic и его службу Storage):

@Injectable()
export class SimpleDataStore {

     private _data: BehaviorSubject<any> = new BehaviorSubject<any>(undefined);
     public data: Observable<any> = this._data.asObservable();

     constructor(private _http: HttpClient, private _storage) {
         this.initializeData();
     }

     private initializeData(): void {
          this._storage.get("dataKey")
              .then(data => this._data.next(data))
              .catch(() => this._data.next([]);
     }

}

Я знаю, как писать асинхронные тесты с помощью Jasmine и как получить доступ к закрытым членам/методам, а также знаю, что нужно проверять _data.getValue() для получения желаемого результата, но моя проблема заключается в том, что я не знаю, как тестировать:

  1. Конструктор и/или;
  2. initializeData, чтобы дождаться завершения промиса, так как в методе не возвращается промис.

Спасибо за любую помощь!


person EHorodyski    schedule 16.01.2019    source источник
comment
Если вы издеваетесь над реализацией _storage, которой можете управлять при разрешении this._storage.get("dataKey"), пробовали ли вы это делать?   -  person Jake Holzinger    schedule 17.01.2019
comment
У меня -- вот так spyOn(TestBed.get(Storage), 'get').and.returnValue(Promise.resolve(localStorage));. Но без установки тестового метода как async - чего я не могу сделать, потому что обещания не возвращаются, я немного потерян.   -  person EHorodyski    schedule 17.01.2019


Ответы (1)


В идеале initializeData() должен возвращать обещание, которое он создает, чтобы вы могли легко дождаться его разрешения в своих тестах. Затем вместо того, чтобы пытаться выяснить, когда обещание разрешается, вы можете просто смоделировать initializeData() до создания класса.

Учитывая, что метод initializeData() изменен для возврата обещания, вы можете протестировать класс SimpleDataStore следующим образом:

describe('SimpleDataStore', function () {

    beforeEach(function () {
        this.initializeData = spyOn(SimpleDataStore.prototype, 'initializeData');
        this.http = jasmine.createSpyObj('HttpClient', ['get']);
        this.storage = jasmine.createSpyObj('Storage', ['get']);
        this.dataStore = new SimpleDataStore(this.http, this.storage);

        // initializeData is called immediately upon construction.
        expect(this.initializeData).toHaveBeenCalled();
    });

    describe('initializeData', function () {

        beforeEach(function () {
            // The data store is initialized, we can now let the calls go to the real implementation.
            this.initializeData.and.callThrough();
        });

        afterEach(function () {
            expect(this.storage.get).toHaveBeenCalledWith('dataKey');
        });

        it('is initialized with "dataKey" storage', function (done) {
            const data = {};
            this.storage.get.and.returnValue(Promise.resolve(data));
            this.dataStore.initializeData()
                .then(() => expect(this.dataStore._data.getValue()).toBe(data))
                .catch(fail)
                .finally(done)
        });

        it('is initialized with empty array when "dataKey" storage rejects', function (done) {
            this.storage.get.and.returnValue(Promise.reject());
            this.dataStore.initializeData()
                .then(() => expect(this.dataStore._data.getValue()).toEqual([]))
                .catch(fail)
                .finally(done)
        });

    });

});
person Jake Holzinger    schedule 17.01.2019
comment
Большое спасибо - я думал, что это будет доступный вариант, но не был уверен, есть ли какой-либо побочный эффект, который я бы упустил, если бы метод возвращал обещание. - person EHorodyski; 17.01.2019
comment
Решение не идеальное, но оно работает. Если вы действительно хотите избежать побочных эффектов, вы можете ввести шаблон фабрики, фабрика может выполнять асинхронную работу по проверке хранилища, а затем создавать объект синхронно с результатом. - person Jake Holzinger; 18.01.2019