繁体   English   中英

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

[英]Ionic Storage v3 - Unit Tests | TypeError: _this.storage.forEach is not a function

我有一个用于@ionic/storage-angularStorageService包装器,其中我有一个 function,大致如下所示:

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 并不认为它是因为我嘲笑它的方式,我假设。

问题是:我如何正确地对这个位进行单元测试? 我不想为测试目的创建一个真实的存储实例,有没有办法通过模拟将 this.storage 定义为可迭代的?

似乎Storage是一个数组。

试试这个快速解锁:

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

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

再次回答我自己的问题。

我的目标是保留我的间谍 object 以模拟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 方法添加到我现有的间谍中:

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

然后模拟返回值

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

从那里开始相当简单。 希望这对将来的人有帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM