When setting up a mock service like this:
// /catalogue/__mock__/catalogue.service.ts
export const CatalogueService = jest.fn().mockImplementation(() => {
return {
filterRulesFor: jest.fn().mockImplementation((role: Roles): Rule[] => rules.filter(r => r.roles.includes(role))
fetchCountries: jest.fn().mockReturnValue(of(countriesStub())),
}
});
In the upcoming structure:
/catalogue
/__mock__
catalogue.service.ts
/tests
catalogue.controller.spec.ts
catalogue.module.ts
catalogue.controller.ts
catalogue.service.ts
The goal is to utilize the mock service within the catalogue.controller.spec.ts
:
// /catalogue/tests/catalogue.controller.spec.ts
import { CatalogueController } from '../catalogue.controller';
import { CatalogueService } from '../catalogue.service';
jest.mock('../catalogue.service'); // <----- manual mocking here
describe('CatalogueController', () => {
let controller: CatalogueController;
let service: CatalogueService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [UtilsModule],
controllers: [CatalogueController],
providers: [CatalogueService],
})
.compile();
controller = module.get<CatalogueController>(CatalogueController);
service = module.get<CatalogueService>(CatalogueService);
jest.clearAllMocks();
});
}
However, encountering an issue when attempting to use it:
describe('getCountries', () => {
let countries: Country[];
beforeEach(async () => {
service.fetchCountries()
.subscribe(countries => console.log(countries)); // <----- here
countries = await firstValueFrom(controller.getCountries());
});
it('should be called', () => {
expect(service.fetchCountries).toBeCalledTimes(1);
});
it('should not be empty', () => {
expect(countries.length).toBe(countriesStub().length);
});
});
Getting a
TypeError: Cannot read property 'subscribe' of undefined
as though the mock service doesn't have the required functions defined.
https://i.sstatic.net/N2mKL.png
If including the mock directly in the same file it works, but that's not the preferred approach:
let controller: CatalogueController;
let service: CatalogueService;
// vvvvv Mock service here vvvv
const mockCatalogueService = {
filterRulesFor: jest.fn().mockImplementation((role: Roles): Rule[] => rules.filter(r => r.roles.includes(role))),
fetchCountries: jest.fn().mockReturnValue(of(countriesStub())),
};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [UtilsModule],
controllers: [CatalogueController],
providers: [CatalogueService],
})
.overrideProvider(CatalogueService) // <--- Implementing here
.useValue(mockCatalogueService) // <--- and here
.compile();
controller = module.get<CatalogueController>(CatalogueController);
service = module.get<CatalogueService>(CatalogueService);
jest.clearAllMocks();
});