есть ли способ в жасмин / синон заглушить вложенные функции вызова? - PullRequest
0 голосов
/ 04 ноября 2019

Я пытаюсь проверить класс, поэтому у меня есть метод в классе core, который вызывает другой метод getDrugsByName. Я написал модульный тест, который будет вызывать core, а затем он также должен вызвать метод заглушки getDrugByName. по какой-то причине тест проходит ниже, но покрытие кода не показывает код, покрытый внутри ядра. Есть идеи, что реализовано неправильно и как заглушить вложенный метод.

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();
            });
    };

1 Ответ

1 голос
/ 05 ноября 2019

Ваше покрытие кода показывает вам, что вы действительно имеете в своих тестах, и позвольте мне быть честным, вы не тестируете свою функцию core, она даже не вызывается, функция может быть полна ошибок и ваших тестовдаже не заметит. Вы вызываете и тестируете функцию-заглушку, которая создается в строке spyOn(Service, 'core').and.callFake, эта строка полностью переопределяет исходную функцию core. Например, вам нужно смоделировать функцию getDrugsByName, но, если в ней много бизнес-логики, вам следует подумать и о написании тестов для этой функции.

Итак, измените ваш тест следующим образом

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();
        });
  };

Обратите внимание на использование spyOn(Service, 'core').and.callThrough(); для отслеживания всех вызовов к нему, но делегирование фактической реализации. Это даст вам полное покрытие кода функции.

Это простое изменение приведет вас к следующему шагу. Но позвольте мне перечислить несколько деталей

  • Вероятно, stubbedHttp не то, что getDrugsByName должен вернуть. Возможно, вам придется настроить его.
  • mockHttp - это undefined , и вы передаете его в качестве аргумента core. Помните об ошибках.
  • _dependencies - это undefined , и вы передаете его в качестве аргумента core. Помните об ошибках.

Надеюсь, это поможет

...