Reputation: 693
I am trying to test class so i have method in the class core
that is calling another method getDrugsByName
. I have wrote the unit test that will call core
and then it should also call stubbed method getDrugByName
. for some reason below test is passing but code coverage is not showing code covered inside core. Any idea what is implemented wrong and how to stubbed nested method.
DrugPriceApi.node.ts
export class DrugPriceApi extends Types.ModuleBase<DrugPriceParam, DrugPriceResultSet[]> {
core(args: DrugPriceParam, requestMethod: Interface.Core.RequestMethod, _dependencies: any): Promise<any> {
this._dependencies = _dependencies;
return new Promise<any>((resolve: Function, reject: Function) => {
if (!_.isEmpty(args.drugName)) {
let drugSearchParam: any = _.cloneDeep(args);
drugSearchParam.searchText = args.drugName;
this.getDrugsByName(drugSearchParam, requestMethod).then((response: any) => {
if (response.header.statusCode === '0000' && _.has(response, 'detail.drugDetailsList.drug')) {
let drugObject = response.detail.drugDetailsList;
let drugFound: boolean = false;
drugObject.drug = Array.isArray(drugObject.drug) ? drugObject.drug : [drugObject.drug];
drugObject.drug.forEach((item: any) => {
if (!drugFound) {
drugFound = ((item.mailDrug && item.mailDrug.ndcId === args.ndcId) || (item.retailDrug && item.retailDrug.ndcId === args.ndcId));
}
});
if (!drugFound) {
reject({
statusDesc: "NDCID does not belong to the Drug Name provided.",
statusCode: "5000",
refId: response.header.refId
});
} else {
this.getDrugPrice(args, drugObject, requestMethod, resolve, reject, this.Handler);
}
}
}).catch((_err: any) => {
reject({
statusCode: '9999',
refId: args.refId,
statusDesc: _err.statusDesc
});
});
}
});
}
}
function getDrugsByName () {
// return Response after making backend call
}
DrugPriceApi.node.spec.ts
import { } from 'jasmine';
import { DrugPriceParam } from "./DrugPriceApi.interface";
import { DrugPriceApi } from "./DrugPriceApi.node";
import sinon from "sinon";
describe("DrugPriceApi", () => {
let stubbedHttp:any;
const successResponse = {
"details": {
"drugDetailsList": {
"drug": [{
"mailDrug": {
"ndcId": "71015523"
},
"drugForm": "Tab"
}]
}
},
"header": {
"statusDesc": "Success",
"statusCode": "0000"
}
};
beforeEach(function() {
// Below are the modules that are called by GetRxHistoryDetails
// since this is a unit test, these modules should not be tested
// these stubs will stop the real modules from executing
stubbedHttp = sandbox.createStubInstance(HttpRequest);
stubbedHttp.makeRequest.callsFake(function() {
return new Promise<any>((resolve) => {
resolve(successResponse);
});
});
});
it("should call Core", function (done) {
let param = {
tokenId: '123',
appName: 'CMK_WEB',
refId: '123'
} as DrugPriceParam;
param.drugName = 'ACITRETIN';
let mockHttp: any;
let _dependencies: any;
let Service = DrugPriceApi.prototype;
spyOn(Service, 'core').and.callFake(() => {
return {
getDrugsByName: function() {
Promise.resolve(stubbedHttp);
}
}
});
Service.core.call(param,mockHttp,_dependencies);
expect(Service.core).toHaveBeenCalled();
done();
});
};
Upvotes: 0
Views: 287
Reputation: 7803
Your code coverage is showing you what you really have in your tests, and let me be honest, you are not testing your core
function, it is not even being invoked, the function can be full of errors and your tests won't even note it. What you are invoking and testing is a stubbed function that is created in the line spyOn(Service, 'core').and.callFake
, that line is completely overriding the original core
function. For example, what you need to mock is getDrugsByName
function, but, if it has a lot of business logic, you need to consider writing tests for that function too.
So, change your test like this
it("should call Core", function (done) {
let param = {
tokenId: '123',
appName: 'CMK_WEB',
refId: '123'
} as DrugPriceParam;
param.drugName = 'ACITRETIN';
let mockHttp: any;
let _dependencies: any;
let Service = DrugPriceApi.prototype;
// spyOn "core" using "callThrough" to track all calls to it but
// delegate to the actual implementation.
spyOn(Service, 'core').and.callThrough();
// spyOn "getDrugsByName" using "returnValue"
spyOn(Service, 'getDrugsByName').and.returnValue(Promise.resolve(stubbedHttp));
Service.core.call(param,mockHttp,_dependencies);
expect(Service.core).toHaveBeenCalled();
done();
});
};
Please, note the use of spyOn(Service, 'core').and.callThrough();
to track all calls to it but delegate to the actual implementation. These will give you full code coverage of the function.
That simple change will take you to the next step. But let me list a few details
stubbedHttp
is not what getDrugsByName
should returns. You might need to adjust it.mockHttp
is undefined and you are passing it as argument to core
. Be aware of errors._dependencies
is undefined and you are passing it as argument to core
. Be aware of errors.Hope it helps
Upvotes: 1