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

如何在不新增参数的情况下用QUnit测试SAPUI5控制器?

Fixing QUnit Test for SAPUI5 Controller Without Modifying Original Function Params

Hey there! I see you're running into an issue where your QUnit test throws an error because rowData[0] is undefined when executing data = dataConnector.getContractHistoryData(rowData[0].M_BIC_B_NSN). You tried adding a testObj parameter to initController but don't like that approach—totally understandable, since modifying production code just for tests isn't ideal. Let's fix this properly by mocking your dependencies instead.

Root Cause of the Error

In your production code, rowData comes from ViewControls.getRowData(). In your test, you defined a local getRowData stub, but you didn't actually replace the ViewControls.getRowData method that your controller uses. That means when the controller runs, rowData ends up as undefined, hence the rowData[0] error.

Step-by-Step Solution

Instead of modifying initController, we'll use Sinon to stub the static methods on ViewControls and dataConnector that your controller depends on. Here's how to adjust your test:

  1. Stub ViewControls.getRowData() to return your test row data, so the controller gets the expected value for rowData.
  2. Stub ViewControls.detailsViewControls.apply(this) to return your mock detailsControls object—this replaces the need for the testObj parameter.
  3. Stub dataConnector.getContractHistoryData() to avoid making real backend calls during testing.
  4. Stub ViewControls.setPriceChangeAccepted() since it's a static method called in initController.

Modified Test Code

QUnit.test("initController setup", function(assert) {
  // Arrange
  var setEnabled = sinon.spy();
  var setValue = sinon.spy();
  var getValue = sinon.spy();
  var setVisible = sinon.spy();
  var setVisibleRowCount = sinon.spy();
  var setValueState = sinon.spy();

  // Test row data
  var testRowData = [
    {
      BAWAEFFDT: "20150213",
      BZZPIIN: "SPE5E967V1599",
      CAGE: "4R840",
      CUR_QTY: "20",
      FAIR_MKT_PRICE: "160.00",
      INDEX: "3",
      M_BIC_B_NSN: "306018040",
      NETPRICE: "150.99",
      ORDER_QUAN: "35",
      PERC_DIFF: "20",
      PROPOSED_PRICE: "25.99",
      PriceReasonableCode: "BG",
      VENDOR: "STAMCO."
    }
  ];

  // Mock detailsControls
  var mockDetailsControls = {
    summaryTable: { setVisibleRowCount: setVisibleRowCount },
    evalPriceButton: { setEnabled: setEnabled },
    nextBtn: { setVisible: setVisible, setEnabled: setEnabled },
    prevBtn: { setVisible: setVisible, setEnabled: setEnabled },
    dropDown: { getValue: getValue, setValue: setValue },
    acceptBtn: { setEnabled: setEnabled },
    awardQuantity: { setValue: setValue, getValue: getValue, setEnabled: setEnabled, setValueState: setValueState },
    missingFieldError: { setVisible: setVisible },
    invalidFieldError: { setVisible: setVisible },
    invalidDateError: { setVisible: setVisible },
    buyQuantity: { setEnabled: setEnabled, setValue: setValue, setValueState: setValueState },
    priorUnitPrice: { setEnabled: setEnabled, setValue: setValue, setValueState: setValueState },
    proposedUnitPrice: { setEnabled: setEnabled, setValue: setValue, setValueState: setValueState },
    awardDate: { setEnabled: setEnabled, setValue: setValue, setValueState: setValueState }
  };

  // Stub all dependencies
  sinon.stub(ViewControls, "getRowData").returns(testRowData);
  sinon.stub(ViewControls, "detailsViewControls").returns(mockDetailsControls);
  sinon.stub(ViewControls, "setPriceChangeAccepted"); // Stub to prevent actual execution
  sinon.stub(dataConnector, "getContractHistoryData").returns([]); // Mock empty history data or test data

  // Act
  detailsController.initController(); // No need to pass testObj anymore!

  // Assert (add your assertions here, e.g.:)
  assert.ok(setEnabled.calledWith(true), "evalPriceButton should be enabled");
  assert.ok(setEnabled.calledWith(false), "acceptBtn should be disabled");
  assert.ok(ViewControls.setPriceChangeAccepted.calledWith(false), "Price change accepted should be set to false");

  // Cleanup: Restore stubs after test
  ViewControls.getRowData.restore();
  ViewControls.detailsViewControls.restore();
  ViewControls.setPriceChangeAccepted.restore();
  dataConnector.getContractHistoryData.restore();
});

Key Changes Explained

  • Stubbed ViewControls.getRowData(): Now the controller gets your test testRowData instead of undefined, so rowData[0] exists.
  • Stubbed ViewControls.detailsViewControls: This replaces the need for the testObj parameter—your mock controls are used automatically via the || fallback in the original code.
  • Stubbed dataConnector.getContractHistoryData(): Prevents real API calls and returns predictable test data.
  • Cleanup: Restoring stubs ensures they don't affect other tests.

This approach keeps your production code untouched while making your test reliable and maintainable.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:11:40