如何为包含 SAPUI5 Core API 的函数编写单元测试?
How to Write Unit Tests for Functions That Contain SAPUI5 Core API?
我是使用 UI5 的 qUnit 新手。
我想测试一个功能formatter.js
formatDate: function(sTimeStamp) {
if (sTimeStamp) {
var iTimeStamp = Number(sTimeStamp.match(/\d/g).join("")),
oDateTimeFormat = DateFormat.getDateTimeInstance();
return oDateTimeFormat.format(new Date(iTimeStamp));
}
return sTimeStamp;
},
对其进行单元测试:
function formatDateTestCase(assert, sValue, fExpectedNumber) {
var fDate = formatter.formatDate(sValue);
assert.strictEqual(fDate, fExpectedNumber, "Format Date was correct");
}
QUnit.test("Should return valid date", function (assert) {
formatDateTestCase.call(this, assert, "/Date(1510026665790)/", "Nov 7, 2017, 11:51:05 AM");
});
显然,当我更改语言设置时,此测试用例将失败。如何改进?
我认为这里的主要问题是 formatDate
是一个有副作用的函数。我应该改进这个功能本身吗?通过在 formatDate
中添加语言环境?
或者我应该在测试用例中使用 DateFormat
吗?这将使我的测试变得毫无意义。
我认为您应该在此处模拟对 DateFormat
的调用,以便能够独立测试您的代码。
单元测试注意事项
严格来说,单元测试的重点是测试你的 - 并且只测试你的 - 单元。你不应该测试任何依赖 API。总的来说,人们可能会对此争论不休,但我绝对不建议测试 SAPUI5 API。
另一方面,我强烈建议使用无效参数(例如 undefined
)和无效字符串测试 if
语句和正则表达式部分。这将确保您的格式化程序始终有效并 return 某事。如果它是一个空字符串,则有意义。
Sinon.JS:模拟、存根和间谍
你应该在你的特定测试中存根 DateFormat.getDateTimeInstance()
以便方法 return 是一个可预测的值(例如,想想 DateFormat
中的 I18N,它会给你不同语言的不同测试结果).
要做到这一点,SAPUI5 已经附带了 Sinon.JS(请注意包含的版本:SAPUI5 1.44 -> Sinon.JS 1.14)。这是一个基本示例:
sap.ui.define([
"my/module/formatter",
"sap/ui/core/format/DateFormat",
"sap/ui/thirdparty/sinon",
"sap/ui/thirdparty/sinon-qunit"
], function (formatter, DateFormat) {
QUnit.test("Should return valid date", function (assert) {
// stub the method
sinon.stub(DateFormat, "getDateTimeInstance");
// ensure a predictable outcome
DateFormat.getDateTimeInstance.returns({
format: function(oDate) {
return oDate.getTime();
}
});
var fDate = formatter.formatDate("/Date(1510026665790)/");
assert.strictEqual(fDate, "1510026665790", "Format Date was correct");
// Optional: test if the stubbed function was called
assert.ok(DateFormat.getDateTimeInstance.calledOnce);
// don't forget to restore the stub so that it does not interfere with other tests
DateFormat.getDateTimeInstance.restore();
});
});
通过存根 DateFormat.getDateTimeInstance
您停止测试核心 API 及其结果,您可以专注于最重要的事情:您的代码。
BR 克里斯
我是使用 UI5 的 qUnit 新手。
我想测试一个功能formatter.js
formatDate: function(sTimeStamp) {
if (sTimeStamp) {
var iTimeStamp = Number(sTimeStamp.match(/\d/g).join("")),
oDateTimeFormat = DateFormat.getDateTimeInstance();
return oDateTimeFormat.format(new Date(iTimeStamp));
}
return sTimeStamp;
},
对其进行单元测试:
function formatDateTestCase(assert, sValue, fExpectedNumber) {
var fDate = formatter.formatDate(sValue);
assert.strictEqual(fDate, fExpectedNumber, "Format Date was correct");
}
QUnit.test("Should return valid date", function (assert) {
formatDateTestCase.call(this, assert, "/Date(1510026665790)/", "Nov 7, 2017, 11:51:05 AM");
});
显然,当我更改语言设置时,此测试用例将失败。如何改进?
我认为这里的主要问题是 formatDate
是一个有副作用的函数。我应该改进这个功能本身吗?通过在 formatDate
中添加语言环境?
或者我应该在测试用例中使用 DateFormat
吗?这将使我的测试变得毫无意义。
我认为您应该在此处模拟对 DateFormat
的调用,以便能够独立测试您的代码。
单元测试注意事项
严格来说,单元测试的重点是测试你的 - 并且只测试你的 - 单元。你不应该测试任何依赖 API。总的来说,人们可能会对此争论不休,但我绝对不建议测试 SAPUI5 API。
另一方面,我强烈建议使用无效参数(例如 undefined
)和无效字符串测试 if
语句和正则表达式部分。这将确保您的格式化程序始终有效并 return 某事。如果它是一个空字符串,则有意义。
Sinon.JS:模拟、存根和间谍
你应该在你的特定测试中存根 DateFormat.getDateTimeInstance()
以便方法 return 是一个可预测的值(例如,想想 DateFormat
中的 I18N,它会给你不同语言的不同测试结果).
要做到这一点,SAPUI5 已经附带了 Sinon.JS(请注意包含的版本:SAPUI5 1.44 -> Sinon.JS 1.14)。这是一个基本示例:
sap.ui.define([
"my/module/formatter",
"sap/ui/core/format/DateFormat",
"sap/ui/thirdparty/sinon",
"sap/ui/thirdparty/sinon-qunit"
], function (formatter, DateFormat) {
QUnit.test("Should return valid date", function (assert) {
// stub the method
sinon.stub(DateFormat, "getDateTimeInstance");
// ensure a predictable outcome
DateFormat.getDateTimeInstance.returns({
format: function(oDate) {
return oDate.getTime();
}
});
var fDate = formatter.formatDate("/Date(1510026665790)/");
assert.strictEqual(fDate, "1510026665790", "Format Date was correct");
// Optional: test if the stubbed function was called
assert.ok(DateFormat.getDateTimeInstance.calledOnce);
// don't forget to restore the stub so that it does not interfere with other tests
DateFormat.getDateTimeInstance.restore();
});
});
通过存根 DateFormat.getDateTimeInstance
您停止测试核心 API 及其结果,您可以专注于最重要的事情:您的代码。
BR 克里斯