I have a dummy service:
export class PatientService extends EntityCollectionServiceBase<Patient> {
constructor(serviceElementsFactory: EntityCollectionServiceElementsFactory) {
super('Patient', serviceElementsFactory);
}
}
I have the following test:
describe('PatientService', () => {
let service: PatientService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(PatientService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
And it gives me:
NullInjectorError: No provider for EntityCollectionServiceElementsFactory
So I updated as follows:
describe('PatientService', () => {
let service: PatientService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [EntityDataModuleWithoutEffects.forRoot(entityConfig)],
providers: [provideMockStore()],
});
service = TestBed.inject(PatientService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
But now it gives me:
NullInjectorError: No provider for ScannedActionsSubject!
How can I properly fix my test?
Because of changes in the latest version of ngrx
, you need to import an empty store modules and HttpClientTestingModule
.
Please check the example below:
describe('PatientService', () => {
let service: PatientService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
PatientService, // <- your entity collection service
// a way to mock the store selectors
provideMockStore(),
],
imports: [
EntityDataModule.forRoot({
entityMetadata: {
Patient: {}, // <- change to your entity
},
pluralNames: {
Patient: 'Patients', // <- change to your entity
},
}),
// can be kept as it is if there are no more dependencies
StoreModule.forRoot({}),
EffectsModule.forRoot([]),
HttpClientTestingModule,
],
});
service = TestBed.inject(PatientService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
Yep, you are very close, do like that. You need to provide in testbed everything what is required for the configuration.
In our case it means that PatientService
should be provided as the testing unit and EntityCollectionServiceElementsFactory
should be provided as its dependency.
But EntityCollectionServiceElementsFactory
has own dependencies: EntityDispatcherFactory
, EntityDefinitionService
, EntitySelectorsFactory
and EntitySelectors$Factory
. Which we don't want to provide because they might have own dependencies making our live worse.
To fix it let's simply sub EntityCollectionServiceElementsFactory
.
describe('PatientService', () => {
let service: PatientService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
PatientService,
{
provide: EntityCollectionServiceElementsFactory,
// our stub
useValue: {
methodsToFake: jasmine.createSpy(),
// ....
},
},
],
});
service = TestBed.inject(PatientService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
Also to avoid the pain of mocking dependencies and its methods in future you can use ng-mocks. Then the test could looks like that:
describe('PatientService', () => {
let service: PatientService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
PatientService,
{
provide: EntityCollectionServiceElementsFactory,
useValue: MockService(EntityCollectionServiceElementsFactory),
},
],
});
service = TestBed.inject(PatientService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});