在SAPUI5中使用Sinon对byId()方法进行Stub的正确方式
我来帮你理清这个问题,你遇到的情况其实是因为对SAPUI5的类继承和Sinon的Stub规则理解有点偏差,咱们一步步拆解解决:
先搞懂两个核心问题的根源
- 用
ManagedObject当View Stub时byId报错:sap/ui/base/ManagedObject是View的父类,但byId是sap/ui/core/mvc/View特有的方法,ManagedObject原型上根本没有这个方法。Sinon默认不允许对不存在的属性做Stub,所以才会抛出"Attempted to wrap undefined property byId as function"的错误。 - 用
View当Stub时的两个错误:大概率是你没正确创建View的Stub实例,只是用了空的Stub对象,导致View原型上的getModel方法没被继承;同时没手动定义viewData属性,控制器访问时自然会报undefined。
正确的View Stub实现方式
下面两种方法都是在控制器测试场景中常用的正确姿势,你可以根据需求选择:
方法1:用Sinon的createStubInstance创建View Stub(最省心)
这个方法会自动继承View原型上的所有方法,不需要手动一个个定义,直接Stub需要的方法即可:
import sinon from "sinon"; import View from "sap/ui/core/mvc/View"; import YourController from "./YourController"; // 导入你的控制器 describe("Your Controller Tests", () => { let oViewStub; let oController; beforeEach(() => { // 创建View的Stub实例,自动继承原型方法 oViewStub = sinon.createStubInstance(View); // 模拟getModel方法,返回一个带Stub的Model const oModelStub = sinon.stub(); oModelStub.getProperty.returns("test-value"); // 按需模拟Model的方法 oViewStub.getModel.returns(oModelStub); // 模拟byId方法,返回你需要的控件Stub const oButtonStub = sinon.stub(); oButtonStub.setVisible.returnsThis(); oViewStub.byId.withArgs("submitButton").returns(oButtonStub); // 手动定义viewData属性,解决undefined错误 oViewStub.viewData = { userId: "test-user-001" }; // 初始化控制器并绑定View Stub oController = new YourController(); oController.setView(oViewStub); }); it("should call getModel and update button visibility", () => { // 执行控制器方法 oController.handleSomeAction(); // 验证Stub方法的调用情况 sinon.assert.calledOnce(oViewStub.getModel); sinon.assert.calledWith(oViewStub.byId, "submitButton"); sinon.assert.calledOnce(oButtonStub.setVisible); }); });
方法2:手动构建View Stub对象(更灵活)
如果只需要模拟控制器用到的少数方法,也可以手动构建Stub对象,确保所有需要的属性/方法都被定义:
import sinon from "sinon"; import YourController from "./YourController"; describe("Your Controller Tests", () => { let oViewStub; let oController; beforeEach(() => { // 手动定义控制器需要的所有View属性和方法 oViewStub = { getModel: sinon.stub().returns({ getProperty: sinon.stub().returns("test-value") }), byId: sinon.stub().returns({ setVisible: sinon.stub() }), viewData: { userId: "test-user-001" }, getController: sinon.stub().returnsThis() // 如果控制器用到这个方法就加上 }; oController = new YourController(); oController.setView(oViewStub); }); // 测试用例... });
额外注意点
- 如果控制器用到了View的其他方法(比如
getLocalId、getParent),要么用createStubInstance自动继承,要么手动在Stub对象里定义。 - 模拟Model时,记得给返回的Model Stub也加上需要的方法(比如
setProperty、bindElement),不然控制器调用时会报错。
内容的提问来源于stack exchange,提问作者Niels
相关产品推荐
相关产品推荐

