Ionic Storage v3 -单元测试| TypeError: _this.storage.forEach不是一个



对于@ionic/storage-angular,我有一个StorageService包装器,其中我有一个函数,看起来大致如下:

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并没有这样认为,因为我嘲笑它的方式,我想。

问题是:我如何正确地对这个位进行单元测试?我不想为测试目的创建一个真正的存储实例,是否有一种方法来定义它。存储通过mock可迭代?

看来Storage是一个数组

试试下面的方法来快速解除阻塞:

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

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

再次回答自己的问题。

我的目标是既保留我的间谍对象来模拟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']);

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

最新更新