Ionic 离子存储v3 -单元测试|类型错误:_this.storage.forEach不是函数

6rvt4ljy  于 2023-01-28  发布在  Ionic
关注(0)|答案(2)|浏览(140)

我有一个@ionic/storage-angularStorageService Package 器,其中有一个函数,大致如下所示:

import { Injectable } from '@angular/core';
import { Storage } from '@ionic/storage-angular';

@Injectable({
  providedIn: 'root'
})
export class StorageService {
  constructor(public storage: Storage) {}

  async getData() {
    const data = [];
    await this.initStorage();

    return new Promise((resolve) => {
      this.storage
        .forEach((value, key) => {
          if (key.startsWith('data-')) {
            data.push({
              key: 'someKey,
              value,
            });
          }
        })
        .then(() => resolve(data));
    });
  }

  // other functions here
}

我有一个单元测试,如下所示

import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { fakeAsync, flush, TestBed } from '@angular/core/testing';
import { StorageService } from './storage.service';
import { Storage } from '@ionic/storage-angular';

describe('StorageService', () => {
  let service: StorageService;
  let mockStorage: jasmine.SpyObj<Storage>;

  beforeEach(() => {
    mockStorage = jasmine.createSpyObj('Storage', ['get', 'set', 'remove', 'create']);

    TestBed.configureTestingModule({
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
      providers: [
        { provide: Storage, useValue: mockStorage },
      ],
    });
    service = TestBed.inject(StorageService);
  });

  describe('getData()', () => {
    it('should call StorageService.initStorage()', fakeAsync(() => {
      spyOn<any>(service, 'initStorage').and.stub();

      service.getData();
      flush();

      expect(service['initStorage']).toHaveBeenCalled();
    }));
  });

  // other tests here
});

它失败于

Error: Uncaught (in promise): TypeError: _this.storage.forEach is not a function
        TypeError: _this.storage.forEach is not a function

存储本身应该是可迭代的,但jasmine并不这么认为,我想是因为我嘲笑它的方式。
问题是:如何正确地对这一位进行单元测试?我不想为测试目的创建一个真实的存储示例,有没有办法通过模拟将www.example.com定义为可迭代的?this.storage as iterable via mocks?

wydwbb8l

wydwbb8l1#

看起来Storage是一个数组。
请尝试以下操作快速解除锁定:

providers: [
        { provide: Storage, useValue: [] },
      ],

我们为Storage提供了一个空数组,因为我们执行的是this.storage.forEach(。您可以根据自己的喜好修改此数组。

k3fezbri

k3fezbri2#

再次回答我自己的问题。
我的目标是既保留我的spy对象来模拟storage.getstorage.set,又能够测试storage.forEach。这似乎是不可能的。上面的答案可能适合那些只需要测试storage.forEach的人。
我决定根本不使用storage.forEach,而是像这样迭代storage.keys

async getData(): Promise<Array<{key: string, value}>> {
    await this.initStorage();

    return this.storage.keys()
      .then(keys => Promise.all(keys
        .filter(key => key.startsWith('data-'))
        .map(async key => {
          const value = await this.storage.get(key);

          return {
            key: 'someKey',
            value,
          }
        })
      ));
  }

这会产生相同的结果,而且更容易测试。我只需要将keys方法添加到我现有的spy中,如下所示:

mockStorage = jasmine.createSpyObj('Storage', ['get', 'set', 'remove', 'create', 'keys']);

然后模拟返回值

mockStorage.keys.and.resolveTo(['different', 'storage', 'keys']);

从那里开始就很简单了。希望这对将来的人有帮助。

相关问题