You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为UI5中attachBrowserEvent编写QUnit测试提升代码覆盖率

问题:QUnit测试中Stub attachBrowserEvent 及解决__sapUiIntegration_card未定义错误

场景说明

需要为控制器中指定代码块编写QUnit测试以提升覆盖率,但运行测试时触发Cannot read properties of undefined (reading '__sapUiIntegration_card')错误,同时不清楚如何Stub attachBrowserEvent方法。

控制器核心代码(需测试部分)

sap.ui.define([
    "sap/ui/core/mvc/Controller",
    "sap/ui/model/json/JSONModel",
     "sap/m/MessageToast",
], function (Controller,JSONModel,MessageToast) {
    "use strict";

    return Controller.extend("com.sap.onesm.supplier.ext.slpCard.supplierContactDetails.Main", {
        // 其他方法省略
        loadData: function(channelId, eventId, oData) {
            console.log('In callback supplierContactDetails.loadData().. ');
            let oController = this;
            var data = oData.vendorData;
            // 需测试的代码块
            oController.oCard = oController.getView().getParent().getComponentData().__sapUiIntegration_card;
            oController.oCard.getCardHeader().attachBrowserEvent("click",function(){
                oController.onPressNavToSMContacts(oData.smVendorId, oData.s4Url);
            });
            // 需测试的代码块结束

            let loaderStatus = oController.getView().getModel("cardState");
            // 后续逻辑省略
            return data[0];
        },
        // 其他方法省略
    });
});

现有测试代码

QUnit.module("Supplier Contacts Card");
let oController = new SupplierContactController();

oController.getView = function() {
    return {
        setModel: function(){},
        getModel: function(){
            return {
                setProperty: function () { }
            }
        },
        getParent: function () { 
            return {
                getComponentData: function() {
                }
            }      
        }
        
    };
};

QUnit.test("check for data", function(assert) {
    let expectedVendorData = [{"Supplier Name":"Ariba Supplier Risk Demo Supplier 111620",
                                "SM Vendor ID":"S25187250",
                                "Primary contact first name": "Drew",
                                "Primary contact last name": "Myers",
                                "Primary contact email": "j.drew.myers@gmail.com"}];
    let expectedOData = {"vendorData" : expectedVendorData, 
    "smVendorId": "S25187250", 
    "s4Url": "sampleURL"};

    oController.onInit();
    let loadDataResult = oController.loadData("", "", expectedOData);
    assert.strictEqual(loadDataResult[0][["contactName"]],"Drew Myers","Contact Name Matched");
    assert.strictEqual(loadDataResult[0][["Primary contact email"]],"j.drew.myers@gmail.com","Email Id Matched");
});

错误信息

Died on test #1     at QUnit.test (https://ui5.sap.com/resources/sap/ui/thirdparty/sinon-qunit.js:34:356)
    at http://localhost:8080/test/unit/controller/SupplierContacts.controller.js:27:11
    at https://ui5.sap.com/resources/sap-ui-core.js:10:16806: Cannot read properties of undefined (reading '__sapUiIntegration_card')@ 1 ms
Expected:   
null
Message:    Diff suppressed as the expected and actual results have an equivalent serialization
Source:     
TypeError: Cannot read properties of undefined (reading '__sapUiIntegration_card')
    at p.loadData (http://localhost:8080/ext/slpCard/supplierContactDetails/SupplierContact.controller.js:28:85)
    at Object.<anonymous> (http://localhost:8080/test/unit/controller/SupplierContacts.controller.js:39:42)
    at Object.i (https://ui5.sap.com/resources/sap/ui/thirdparty/sinon.js:220:476)
    at Object.e (https://ui5.sap.com/resources/sap/ui/thirdparty/sinon.js:220:794)

解决方案

1. 修复__sapUiIntegration_card未定义问题

补全getComponentData的返回值,添加__sapUiIntegration_card对象,并为其提供getCardHeader方法,该方法返回包含attachBrowserEvent的模拟对象。

2. Stub attachBrowserEvent并验证逻辑

使用Sinon.js的stub模拟attachBrowserEvent,同时用spy监听目标方法,验证点击事件触发时的调用逻辑。

修改后的测试代码

QUnit.module("Supplier Contacts Card");
let oController = new SupplierContactController();

let attachBrowserEventStub;
let onPressSpy;

QUnit.beforeEach(function() {
    // 创建spy监听导航方法,用于验证调用
    onPressSpy = sinon.spy(oController, "onPressNavToSMContacts");
    
    // 完整模拟视图-组件数据-card的调用链
    oController.getView = function() {
        // 模拟cardHeader对象,包含attachBrowserEvent stub
        const oCardHeader = {
            attachBrowserEvent: sinon.stub().callsArg(1) // 自动触发传入的回调函数,模拟点击
        };
        
        return {
            setModel: function(){},
            getModel: function(){
                return {
                    setProperty: function () { }
                }
            },
            getParent: function () { 
                return {
                    getComponentData: function() {
                        return {
                            __sapUiIntegration_card: {
                                getCardHeader: function() {
                                    return oCardHeader;
                                }
                            }
                        };
                    }
                }      
            }
        };
    };
});

QUnit.afterEach(function() {
    // 恢复spy,避免影响其他测试
    onPressSpy.restore();
});

QUnit.test("check for data and card header click event", function(assert) {
    let expectedVendorData = [{"Supplier Name":"Ariba Supplier Risk Demo Supplier 111620",
                                "SM Vendor ID":"S25187250",
                                "Primary contact first name": "Drew",
                                "Primary contact last name": "Myers",
                                "Primary contact email": "j.drew.myers@gmail.com"}];
    let expectedOData = {"vendorData" : expectedVendorData, 
    "smVendorId": "S25187250", 
    "s4Url": "sampleURL"};

    oController.onInit();
    let loadDataResult = oController.loadData("", "", expectedOData);
    
    // 验证数据处理逻辑
    assert.strictEqual(loadDataResult.contactName,"Drew Myers","Contact Name Matched");
    assert.strictEqual(loadDataResult["Primary contact email"],"j.drew.myers@gmail.com","Email Id Matched");
    
    // 验证attachBrowserEvent是否被正确调用
    const oCardHeader = oController.getView().getParent().getComponentData().__sapUiIntegration_card.getCardHeader();
    assert.ok(oCardHeader.attachBrowserEvent.calledOnceWith("click"), "attachBrowserEvent called with click event");
    
    // 验证点击回调触发时,导航方法是否被正确调用
    assert.ok(onPressSpy.calledOnceWith(expectedOData.smVendorId, expectedOData.s4Url), "onPressNavToSMContacts called with correct parameters");
});

关键说明

  • 完整模拟调用链:补全getView().getParent().getComponentData().__sapUiIntegration_card.getCardHeader()的每一层返回值,避免undefined错误。
  • Stub事件绑定方法:用Sinon的stub替代attachBrowserEvent,并通过callsArg(1)自动触发回调,模拟用户点击行为。
  • Spy验证业务逻辑:通过spy监听onPressNavToSMContacts,验证点击事件是否正确触发了目标方法,且参数符合预期。

内容的提问来源于stack exchange,提问作者Abhilasha Dahiya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 19:00:53