I have a service that is utilized with NestJS, although the issue at hand is not specific to NestJS. Nonetheless, testing in NestJS is involved, and I use it to create the service for testing purposes. This service is responsible for making multiple calls and returning all the gathered data.
In my particular case, there is a service (myservice) which retrieves results (an object of data) by combining information from various sources. These external sources are all Promise-based using async/await functionality and are used to gather different data points, which are then combined within the myservice (a base service extended by others) to handle error management, processing of promise results, etc.
The challenge I am facing revolves around mocking the external calls for testing. Specifically, the difficulty lies in mocking the function responsible for fetching data from NodeJS. While I can test this function independently without any problems, attempting to mock out this function call within my service leads to complications.
Here's a brief excerpt of the functions under consideration as part of: myservice.ts
public async GetData(DataType: number = DATA_TYPES.TEXT): Promise<ResultFile> {
const ResultData: ResultFile = new ResultFile(DataType);
return new Promise<ResultFile>((resolve, reject) => {
const Data$: Promise<string> = this.GetResultFileContents();
const StatusCode$: Promise<number> = this.GetResultFileStatusCode();
Promise.all([Data$, StatusCode$])
.then((Results) => {
ResultData.Contents = Results[0]; // Promise returns a string
ResultData.StatusCode = Results[1]; // Promise returns a number
resolve(ResultData);
})
.catch((Exception: Error) => {
ResultData.StatusCode = HttpStatus.NOT_FOUND;
ResultData.Contents = Exception.message;
reject(ResultData);
});
});
}
The above method is the core operation dedicated to retrieving various data. It triggers more promises than the mentioned 2, but these two serve to exemplify the issue.
public async GetResultFileContents(): Promise<string> {
try {
const Results$: string = await ReadFileContents(this.Directory_, this.BaseName_);
return Results$;
} catch (Exception) {
throw new HttpException(`File not found: ${this.BaseName_} in ${this.Directory_}`, HttpStatus.NOT_FOUND);
}
}
public async GetResultFileStatusCode(): Promise<number> {
let StatusCode: number = 0;
try {
const StatusCodeFile: string = `${this.BaseName_}.err`;
const StatusCodeData$ = await ReadFileContents(this.Directory_, StatusCodeFile);
StatusCode = GetIntegerFromText(StatusCodeData$);
} catch (Exception) {
StatusCode = HttpStatus.OK; // Return OK since a specific status was not set to be returned.
}
return new Promise<number>((resolve) => {
resolve(StatusCode);
});
}
The two methods being called to return promises both invoke an external function, ReadFileContents(). This is the function I aim to mock as it provides the data as a string or raises an exception encapsulating OS checks among other tasks related to the file(s) containing the data.
This function is commonly shared by several methods responsible for reading data from the file system. Similar issues exist with REST calls, though this example simplifies matters.
The issue surfaces in the test file. Though I can successfully test the service and its internal methods within myservice.ts
, I'm unsure how to effectively mock the external call to ReadFileContents() to verify proper execution of my methods in myservice.ts
.
I aim to examine varying return strings along with exception handling when files are missing, among other scenarios.
My test:
import { Test, TestingModule } from '@nestjs/testing';
import { MyService } from './my.service';
// TODO: Need to mock the internal calls to ReadFileContents() to throw exceptions
describe('MyService (mock)', () => {
let service: MyService;
afterEach(() => {});
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [MyService],
}).compile();
service = module.get<MyService>(MyService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
it('should handle exceptions when reading missing .hdr file', async () => {
// const mockReadFileContents = jest.spyOn(service.???);
});
});
In the last function, I'm uncertain about mocking ReadFileContents as it's merely a function within the service located in another source file.
I wish to avoid creating a public method in the service solely for calling this function to enable proper mocking, if possible.
Please disregard any missing functions or typos as this was a quick edit to showcase what I aim to achieve.