I have a method, that I want to unit test, but in the method there is a dependency to a storageService. I don't understand, how I can mock the dependency the right way so the mock is called instead and returns a certain value. Please help me.
import { TestBed } from '@angular/core/testing';
import { ProductDataService } from './product-data.service';
import { StorageService } from './storage.service';
describe('ProductDataService', () => {
let service: ProductDataService;
let storageServiceSpy;
let mockFileId, getMock;
getMock = (key: string): Promise<any> => {
return new Promise((resolve, reject) => {
if (key == "PRODUCT_DATA_INFO_LOCAL") {
return resolve();
} else {
return reject();
}
})
}
beforeEach(() => {
mockFileId = "test";
storageServiceSpy = jasmine.createSpyObj('StorageService', ['get', 'set']);
TestBed.configureTestingModule({
imports: [],
providers: [
{ provide: StorageService, useValue: storageServiceSpy }
]
});
service = TestBed.inject(ProductDataService);
});
it('should call getFileInfo and resolve', (done) => {
let spy = spyOn(storageServiceSpy, 'get').and.callFake(getMock("PRODUCT_DATA_INFO_LOCAL"));
service['getFileInfo'](mockFileId).then((data) => {
expect(spy).toHaveBeenCalled();
done();
})
})
});
Jasmine gives me the following error:
Error: : get has already been spied upon
CodePudding user response:
I mangaged to do it by myself. Here is the code:
describe('ProductDataService', () => {
let fixture: ComponentFixture<ProductDataService>;
let component: ProductDataService;
let service: ProductDataService;
let mockFileId;
const mockStorageService = {
get: () => {return Promise.resolve();}
}
beforeEach(async(() => {
mockFileId = "test";
TestBed.configureTestingModule({
providers: [
{ provide: StorageService, useValue: mockStorageService }
]
})
service = TestBed.inject(ProductDataService);
}));
it('should call getFileInfo and resolve', async (done) => {
let spy = spyOn<any>(mockStorageService, 'get').and.resolveTo(['foo', 'bar']);
service['getFileInfo'](mockFileId).then((data) => {
expect(spy).toHaveBeenCalled();
done();
})
})
});
I think the key was mocking the service as a const on the one hand and on the other hand creating the spy later in the test case. I also declared the test-case as async, because of these timeout errors. Maybe someone knows more about it?
CodePudding user response:
OK, I tried it without the double spy:
beforeEach(() => {
storageServiceSpy = jasmine.createSpyObj('StorageService', {get: getMock, set: null});
TestBed.configureTestingModule({
providers: [
{ provide: StorageService, useValue: storageServiceSpy }
]
});
service = TestBed.inject(ProductDataService);
});
it('should call getFileInfo and resolve', (done) => {
service['getFileInfo'](id).then(() => {
expect(storageServiceSpy).toHaveBeenCalled();
done();
})
})
With the solution above, I get:
Error: Timeout - Async function did not complete within 5000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL)