javascript - 在 Jasmine/Node.js 中测试独立的 JS 文件
问题描述
我在 node.js 应用程序中有一个独立的 javascript 文件 cacheBustingInterceptor.js。它是一种工厂模式的服务,当应用程序持有时由 app.js 调用。
/**
* Intercept the http request
* If the config.url is from upload or templates and is a html file
* append the cacheBusting Param
* If the template url has query param exisitng
* append &_dt=epochtime else append ?_dt=epochtime
*/
var cacheBustingInterceptor = {
CacheBustingService: CacheBustingServiceFactory
};
function CacheBustingServiceFactory() {
function CacheBustingService() {}
var possibleHtmlPaths = ['templates', 'upload'];
CacheBustingService.prototype.appendCacheBustingParam = function(templateUrl) {
for (var index = 0; index != possibleHtmlPaths.length; index++) {
// check if the url has is .html and from upload and templates
var addCacheBusting = templateUrl.indexOf(possibleHtmlPaths[index]) != - 1 &&
templateUrl.indexOf('.html') != - 1;
var hasQueryParams = templateUrl.indexOf('?') != -1;
if (addCacheBusting) {
if (hasQueryParams) {
return templateUrl + window.appendCacheBustingParam;
} else {
return templateUrl + window.cacheBustingParam;
}
}
}
return templateUrl;
};
CacheBustingService.prototype.interceptRequest = function() {
var _this = this;
var cacheBuster = {
request: function (config) {
config.url = _this.appendCacheBustingParam(config.url);
return config;
}
}
return cacheBuster;
}
return CacheBustingService;
}
我们调用它的方式是在配置中的 app.js 中添加一个注入器,并将工厂推送到配置中。
像这样,
app. config([''$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('templateCacheBustingInjector');
app.factory('templateCacheBustingInjector', ['$injector', function
($injector) {
var CacheBustingService =
$injector.invoke(cacheBustingInterceptor.CacheBustingService);
var cacheBustingService = new CacheBustingService();
return cacheBustingService.interceptRequest();
}]);
现在这一切正常,但我想在 cacheBustingInterceptor.js 中对方法“appendCacheBustingParam”进行单元测试,并且没有想法从 jasmine 单元测试中调用它
事情累了:1.调用我在app.js中调用的方式,但我得到服务注入错误或提供程序错误2.使用require加载js文件但不支持require,我尝试使用browsify,但是,这也没有帮助.
require('../main/webapp/media/scripts/cacheBustingInterceptor.js');
fdescribe('Cache Busting Service', function() {
var cacheBustingService;
var $injector;
beforeEach((inject(function (_$injector_) {
$injector = _$injector_;
$injector.get(cacheBustingInterceptor.CacheBustingService);
// var CacheBustingService = $injector.invoke(cacheBustingInterceptor.CacheBustingService);
})));
it('Test appendCacheBustingParam', function() {
cacheBustingService = new CacheBustingService();
spyOn(cacheBustingService.prototype, 'appendCacheBustingParam');
expect(cacheBustingService.prototype).toHaveBeenCalled();
});
});
解决方案
我认为当您说“独立”时,这里存在术语问题。
单元测试测试一个独立的代码单元。
集成测试测试孤立单元之间的交互。
您的方法的单元测试可能类似于
const mock = {}; // fill with appropriate properties
const result = CacheBustingService
.prototype
.appendCacheBustingParam
.call(mock, someURL);
expect(result).toBe(expectedResult);
单元测试不应该要求连接服务。单元测试通常应该可以在节点中从命令行运行,理想情况下甚至不需要运行,npm install
因为你已经把所有东西都存根了。您的单元测试应该运行亚秒级。最好用于整个套件,但这可能取决于代码库的大小。
听起来你想要的是一个集成测试:创建服务实际上是否正确地连接了所有东西?
在集成测试的情况下,实际构建服务以找出答案是完全有意义的,这意味着在浏览器中运行它,例如 karma 和实际依赖项(而不是作为独立文件)。集成测试可能会更慢/运行更少。
最后一点
您的方法不太适合自动化测试,因为它引用全局变量并通过窗口执行此操作:
if (hasQueryParams) {
return templateUrl + window.appendCacheBustingParam;
} else {
return templateUrl + window.cacheBustingParam;
}
将这些参数改为方法。
推荐阅读
- css - 自定义复选框按钮问题
- sql - oracle 程序的多值
- sockets - sin_addr 总是返回 0.0.0.0
- database - Asp.Net核心从数据库中的表中删除一个条目:结果是什么
- django - 使用 Django ORM 值并调用成员函数
- javascript - 在 Firefox 下加载文件“EventLog.js”失败
- rest - 应用程序的 Twitter API 限制
- java - 如何从内部和外部存储中获取歌曲?
- azure-storage - 如何为 Azure 存储 blob 静态网站启用 Azure CDN?
- ruby - 在appium中获取文本颜色