I have a component that I am trying to setup and test using TestBed.
This component contains one class that has a parameter in the constructor that is an interface, not a concrete class. This interface is satisfied by whatever class I choose to use (either the real one, or a mok one for unit testing). But when I am constructing the component that uses this service in TestBed, I cannot figure out how to define that parameter to the TestBed configuration.
Here is the TestBed config for the component:
describe('PanelContentAreaComponent', () => {
let component: PanelContentAreaComponent;
let fixture: ComponentFixture<PanelContentAreaComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PanelContentAreaComponent
],
providers:[
MenuCommandService, ProcedureDataService, IOpenService],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
.compileComponents();
}));
The service which is having trouble being constructed in TestBed is ProcedureDataService . It's definition is below:
@Injectable()
export class ProcedureDataService {
serverOpenFile: OpenFile;
constructor(private _openService: IOpenService) {
this.serverOpenFile = emptyFileStatus;
}
The one parameter in the constructor of the ProcedureDataService
is IOpenService
whose definition is :
export interface IOpenService {
openFile(fileType: string, dataType: string, filePath: string) ;
}
As you can see this is an interface, not a concrete class.
In my service unit test, we mock the IOpenService by implementing it as follows:
export class mockOpenService implements IOpenService{
constructor(){}
openFile(fileType: string, dataType: string, filePath: string) {
let fileContent: OpenFile;
...
...
[fake the data with mok junk]
...
fileContent = {
'filePath': filePath,
'fileName': name,
'openSuccess': isSuccess,
'error': errorMsg,
'fileData': jsonData
};
return Observable.of(fileContent);
}
}
This works great in the ProcedureDataService service unit test. And, of course, in the real code, we implement the IOpenService with the full implemented file open service that gets the data properly.
But in trying to use this service inside of a component I get the following error:
PanelContentAreaComponent should create FAILED
Failed: IOpenService is not defined
ReferenceError: IOpenService is not defined
This makes sense, so then I am trying to figure out how to tell TestBed that I have a concrete class implementation of this IOpenService which I wish to use. I tried this, but it fails:
describe('PanelContentAreaComponent', () => {
let component: PanelContentAreaComponent;
let fixture: ComponentFixture<PanelContentAreaComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PanelContentAreaComponent
],
providers:[
{provide: IOpenService, useClass: mockOpenService},
MenuCommandService, ProcedureDataService, IOpenService],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
.compileComponents();
}));
The compiler is telling me:
(31,19): error TS2693: 'IOpenService' only refers to a type, but is being used as a value here.
and I am still getting :
PanelContentAreaComponent should create FAILED
Failed: IOpenService is not defined
ReferenceError: IOpenService is not defined
So how do I instruct TestBed
that I have a specific class (mockOpenService
) implementation of an interface parameter (IOpenService
) needed for the service (ProcedureDataService
) being provided to test this component (PanelContentAreaComponent
)?