我正在尝试在新的Angular 7 / Ionic 4应用程序中使用Testbed,但由于我的组件依赖于Ionic本机插件storage,因此无法运行任何测试。
app.component.spec.ts
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import {TestBed, async, fakeAsync, tick} from '@angular/core/testing';
import { Platform } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import {RouterTestingModule} from '@angular/router/testing';
import {Router} from '@angular/router';
import {Location} from '@angular/common'
import { LoginPage } from './pages/login/login.page';
import { routes } from "./app-routing.module";
import {HttpClientTestingModule} from '@angular/common/http/testing';
import {StorageMock} from './testing/mocks/storage.mock';
import {IonicStorageModule} from '@ionic/storage';
describe('AppComponent', () => {
let statusBarSpy, splashScreenSpy, platformReadySpy, platformSpy, storageSpy;
let router: Router;
let location: Location;
let fixture;
let comp: AppComponent;
beforeEach(async(() => {
statusBarSpy = jasmine.createSpyObj('StatusBar', ['styleDefault']);
splashScreenSpy = jasmine.createSpyObj('SplashScreen', ['hide']);
platformReadySpy = Promise.resolve();
platformSpy = jasmine.createSpyObj('Platform', { ready: platformReadySpy });
storageSpy = jasmine.createSpyObj('Storage', ['get', 'set', 'clear', 'remove', 'ready']);
TestBed.configureTestingModule({
declarations: [AppComponent],
imports: [
RouterTestingModule.withRoutes(routes),
IonicStorageModule.forRoot(),
HttpClientTestingModule,
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [
{ provide: StatusBar, useValue: statusBarSpy },
{ provide: SplashScreen, useValue: splashScreenSpy },
{ provide: Platform, useValue: platformSpy },
{ provide: Storage, useClass: StorageMock }
],
}).compileComponents();
router = TestBed.get(Router);
location = TestBed.get(Location);
fixture = TestBed.createComponent(AppComponent);
comp = fixture.componentInstance;
router.initialNavigation();
}));
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});
it('should initialize the app', async () => {
TestBed.createComponent(AppComponent);
expect(platformSpy.ready).toHaveBeenCalled();
await platformReadySpy;
expect(statusBarSpy.styleDefault).toHaveBeenCalled();
expect(splashScreenSpy.hide).toHaveBeenCalled();
});
it('navigates to "" redirects you to /login', fakeAsync(() => {
router.navigate(['']);
tick();
expect(location.path()).toBe('/login')
}));
afterEach(() => {
fixture.destroy();
comp = null
})
});
并创建了自己的 StorageMock :
import {Storage, StorageConfig} from '@ionic/storage';
export class StorageMock extends Storage {
driver: string;
vals: {};
constructor(config: StorageConfig) {
super({})
}
clear() {
return new Promise<void>((res) => res())
}
ready() {
return new Promise<LocalForage>((res) => res())
}
get(key: string) {
return new Promise((res) => res(this.vals[key]))
}
set(key, val) {
return new Promise((res) => {
this.vals[key] = val;
res()
})
}
remove(key) {
return new Promise((res) => {
delete this.vals[key];
res()
})
}
}
但是,当我运行测试时,我仍然看到:
Error: Can't resolve all parameters for Storage: (?).
我想念什么?
答案 0 :(得分:2)
首先,导入存储空间:
import { Storage } from '@ionic/storage';
为模拟创建一个常量:
const storageIonicMock: any = {
get: () => new Promise<any>((resolve, reject) => resolve('As2342fAfgsdr')),
set: () => ...
};
配置TesBed
TestBed.configureTestingModule({
imports: [],
providers: [
{
provide: Storage,
useValue: storageIonicMock
}
]
});
答案 1 :(得分:1)
Ionic插件storage也可以在浏览器环境中使用。
您无需创建模拟,您可以直接将其导入,定义并注入到您的组件中(如果您在浏览器环境中运行测试):
首次导入:
import { Storage } from '@ionic/storage';
import { MyComponent } from './my-component';
声明一个全局组件变量:
let component: MyComponent;
然后,对于每个测试,在组件中定义并注入存储:
beforeEach(() => {
const storage = new Storage({ // Define Storage
name: '__mydb',
driverOrder: ['indexeddb', 'sqlite', 'websql']
});
component = new MyComponent(storage); // Inject Storage in your component
}
答案 2 :(得分:0)
正如其他人所写,存储可以在浏览器中工作,因此我不需要模拟它来进行测试。 这对我有用(StorageWrapperService是我的服务,取决于Ionic的存储):
import { TestBed } from '@angular/core/testing';
import { StorageWrapperService } from './storage-wrapper.service';
import { IonicStorageModule, Storage } from '@ionic/storage';
describe('StorageWrapperService', () => {
let service: StorageWrapperService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
IonicStorageModule.forRoot({
name: '__mydb',
driverOrder: ['localstorage']
})
],
});
service = TestBed.inject(StorageWrapperService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
其他信息:
在两次测试之间不会清除localstorage,所以您可能想使用如下代码:
describe('StorageWrapperService', () => {
let service: StorageWrapperService;
let storage: Storage;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
IonicStorageModule.forRoot({
name: '__mydb',
driverOrder: ['localstorage']
})
]
});
service = TestBed.inject(StorageWrapperService);
storage = TestBed.inject(Storage);
});
...
});
在每次测试结束时清除存储空间:
it('...', (done) => {
storage.clear().then(() => done());
});