第28步:使用QUnit进行单元测试

本文档介绍了如何在应用程序中使用QUnit为自定义格式化器函数添加单元测试。通过模拟ResourceBundle和控制器,确保测试独立于其他组件,并详细解释了测试的安排、系统测试和断言部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明

现在我们在应用程序中有了一个测试文件夹,我们可以开始增加测试范围了。


实际上,到目前为止,我们添加到应用程序中的每个功能都需要一个单独的测试用例。到目前为止,我们完全忽略了这一点,所以让我们为步骤23中的自定义格式化器函数添加一个简单的单元测试。我们将通过比较来自资源包的文本来测试状态的长文本是否正确。


注意
在本教程中,我们测试一个简单实现的用例。如果您想了解更多关于QUnit测试的知识,请查看我们的测试教程,特别是第2步:第一个单元测试

预览

在这里插入图片描述

现在可以对格式化器进行单元测试了

代码

您可以在演练-步骤28查看和下载所有文件。

在这里插入图片描述

此步骤的文件夹结构

我们在test文件夹下添加了一个新的文件夹unit,在model子文件夹中放置格式化器单元测试。文件夹结构与应用程序结构相匹配,可以轻松找到相应的单元测试。

webapp/test/unit/model/formatter.js

/*global QUnit*/

sap.ui.define([
	"sap/ui/demo/walkthrough/model/formatter",
	"sap/ui/model/resource/ResourceModel"
], function (formatter, ResourceModel) {
	"use strict";

	QUnit.module("Formatting functions", {
		beforeEach: function () {
			this._oResourceModel = new ResourceModel({
				bundleUrl: sap.ui.require.toUrl("sap/ui/demo/walkthrough") + "/i18n/i18n.properties"
			});
		},
		afterEach: function () {
			this._oResourceModel.destroy();
		}
	});


	QUnit.test("Should return the translated texts", function (assert) {

		// Arrange
		// this.stub() does not support chaining and always returns the right data
		// even if a wrong or empty parameter is passed.
		var oModel = this.stub();
		oModel.withArgs("i18n").returns(this._oResourceModel);
		var oViewStub = {
			getModel: oModel
		};
		var oControllerStub = {
			getView: this.stub().returns(oViewStub)
		};

		// System under test
		var fnIsolatedFormatter = formatter.statusText.bind(oControllerStub);

		// Assert
		assert.strictEqual(fnIsolatedFormatter("A"), "New", "The long text for status A is correct");

		assert.strictEqual(fnIsolatedFormatter("B"), "In Progress", "The long text for status B is correct");

		assert.strictEqual(fnIsolatedFormatter("C"), "Done", "The long text for status C is correct");

		assert.strictEqual(fnIsolatedFormatter("Foo"), "Foo", "The long text for status Foo is correct");
	});

});

我们在webapp/test/unit/model下创建了一个新的formatter.js文件,其中实现了自定义格式化器的单元测试。我们想要测试的格式化程序文件作为依赖项加载。我们还需要一个对ResourceModel的依赖关系,因为我们想要检查翻译的文本是否正确。

格式化程序文件只包含一个用于格式化程序功能的QUnit模块。它用beforeEach函数中的本地化文本实例化我们的ResourceBundle,并在afterEach函数中再次销毁它。在执行每个测试之前和之后都会调用这些函数。

接下来是formatter函数的单元测试。
在我们在第23步中创建的statusText函数的实现中,我们使用以下队列调用:
var resourceBundle = this.getView().getModel(“i18n”).getResourceBundle();
访问ResourceBundle。

由于我们不想测试控制器、视图或模型功能,我们首先通过SinonJS及其stub方法将这些调用替换为空外壳来移除依赖。这发生在单元测试的Arrange部分。SinonJS为所有对象注入一个存根方法,因此我们可以简单地调用this.stub()来为我们需要模拟的任何行为创建一个新的存根。

测试存根是具有预编程行为的函数。除了可以用来改变存根行为的方法外,它们还支持完整的SinonJS测试间谍API。如果这部分有一点困惑,请查看官方的SinonJS文档测试间谍或忽略它,它将在稍后变得清楚。

然后通过调用JavaScript的bind函数将存根绑定到statusText格式化器。当使用变量fnIsolatedFormatter调用函数时,this指针现在被绑定到控制器存根上,我们仍然可以按照自己的想法传递参数。这发生在测试的“system under test”部分。

最后,我们执行断言。通过使用数据模型中期望的值(A、B、C和其他所有值)调用独立的格式化程序函数,我们检查格式化程序逻辑的每个分支。我们严格地将formatter函数的结果与我们期望从资源包中得到的硬编码字符串进行比较,并在测试失败时给出有意义的错误消息。我们在这里硬编码字符串,以识别资源包属性的问题。如果缺少一个属性,如果我们根据资源包的实际值(两边都是空字符串)进行检查,测试仍然会成功。

webapp/test/unit/unitTests.qunit.html (New)

<!DOCTYPE html>
<html>
<head>
	<title>Unit tests for SAPUI5 Walkthrough</title>
	<meta charset="utf-8">

	<script
		id="sap-ui-bootstrap"
		src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
		data-sap-ui-resourceroots='{
			"sap.ui.demo.walkthrough": "../../"
		}'
		data-sap-ui-async="true">
	</script>

	<link rel="stylesheet" type="text/css" href="https://openui5.hana.ondemand.com/resources/sap/ui/thirdparty/qunit-2.css">

	<script src="https://openui5.hana.ondemand.com/resources/sap/ui/thirdparty/qunit-2.js"></script>
	<script src="https://openui5.hana.ondemand.com/resources/sap/ui/qunit/qunit-junit.js"></script>
	<script src="https://openui5.hana.ondemand.com/resources/sap/ui/qunit/qunit-coverage.js"></script>
	<script src="https://openui5.hana.ondemand.com/resources/sap/ui/thirdparty/sinon.js"></script>
	<script src="https://openui5.hana.ondemand.com/resources/sap/ui/thirdparty/sinon-qunit.js"></script>

	<script src="unitTests.qunit.js"></script>
</head>
<body>
	<div id="qunit"/>
	<div id="qunit-fixture"/>
</body>
</html>

所谓的QUnit测试套件是一个HTML页面,它会触发应用程序的所有QUnit测试。它的大部分内容是生成您可以在预览中看到的结果页面的布局,我们不会进一步解释这些部分,而是将重点放在应用程序部分。

让我们从名称空间开始。因为我们现在在webapp/test/unit文件夹中,我们实际上需要上两层去再次获得src文件夹。可以在测试中使用此名称空间来加载和触发应用程序功能。

首先,我们通过脚本标签加载一些基本的QUnit功能。还可以在这里添加其他QUnit测试。然后,HTML页面加载另一个名为unitTests.qunit.js的脚本,我们将在接下来创建它。这个脚本将执行我们的格式化程序。

webapp/test/unit/unitTests.qunit.js (New)

/* global QUnit */

QUnit.config.autostart = false;

sap.ui.getCore().attachInit(function () {
	"use strict";

	sap.ui.require([
		"sap/ui/demo/walkthrough/test/unit/model/formatter"
	], function () {
		QUnit.start();
	});
});

这个脚本加载并执行格式化程序。如果我们现在在浏览器中打开webapp/test/unit/unitTests.qunit.html文件,我们应该看到我们的测试正在运行并验证格式化程序逻辑。

约定

  • 所有单元测试都放在应用程序的webapp/test/unit文件夹中。
  • 测试套件中的文件以 *.qunit.html结尾。
  • unitTests.qunit.html文件会触发应用程序的所有单元测试。
  • 应该为格式化程序、控制器逻辑和其他单独的功能编写单元测试。
  • 所有依赖项都由存根替换,仅测试范围中的功能。

相关信息

章节

  1. 第1步:你好世界
  2. 第2步:引导
  3. 第3步:控件
  4. 第4步:XML视图
  5. 第5步:控制器
  6. 第6步:模块
  7. 第7步:JSON模型
  8. 第8步:可翻译的文本
  9. 第9步:组件配置
  10. 第10步:应用程序描述符
  11. 第11步:页面和面板
  12. 第12步:Shell控件作为容器
  13. 第13步:外边距和内边距
  14. 第14步:自定义CSS和主题颜色
  15. 第15步:嵌套视图
  16. 第16步:对话框和片段
  17. 第17步:片段回调
  18. 第18步:图标
  19. 第19步:重用对话框
  20. 第20步:聚合绑定
  21. 第21步:数据类型
  22. 第22步:表达式绑定
  23. 第23步:自定义格式器
  24. 第24步:过滤
  25. 第25步:排序和分组
  26. 第26步:远程OData服务
  27. 第27步:模拟服务器配置
  28. 第28步:使用QUnit进行单元测试
  29. 第29步:与OPA的集成测试
  30. 第30步:调试工具
  31. 第31步:路由和导航
  32. 第32步:路由与参数
  33. 第33步:路由回溯和历史
  34. 第34步:自定义控件
  35. 第35步:响应性
  36. 第36步:设备适应
  37. 第37步:内容密度
  38. 第38步:可访问性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值