【问题标题】:Test standalone JS file in Jasmine/Node.js在 Jasmine/Node.js 中测试独立的 JS 文件
【发布时间】:2019-07-12 08:17:17
【问题描述】:

我在 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();
});

});

【问题讨论】:

  • 由于 CacheBustingService 以任何方式与 AngularJS 一起使用,因此将其编写为提供程序是有意义的。如果您像往常一样使用 DI,就不会在测试时遇到此类问题。此外,答案已经包含有关此代码的有效点。

标签: javascript node.js jasmine karma-jasmine karma-runner


【解决方案1】:

我认为当您说“独立”时,这里存在术语问题。

单元测试测试一个独立的代码单元。

Intergration 测试测试 隔离单元之间的交互。

您的方法的 unit 测试可能类似于

const mock = {}; // fill with appropriate properties
const result = CacheBustingService
  .prototype
  .appendCacheBustingParam
  .call(mock, someURL);

expect(result).toBe(expectedResult);

单元测试不应要求连接服务。单元测试通常应该可以从命令行在节点中运行,理想情况下甚至不需要运行npm install,因为您已经将所有内容都存根了。您的单元测试应该运行亚秒级。最好用于整个套件,但这可能取决于代码库的大小。

听起来你想要的是一个集成测试:创建服务实际上是否正确地连接了所有东西?

在集成测试的情况下,实际上构建服务以找出答案是完全有意义的,这意味着在浏览器中运行它,例如业力和实际的依赖关系(不是作为独立文件)。集成测试可能会更慢/运行频率更低。

最后一点

您的方法不太适合自动化测试,因为它引用全局变量并通过窗口进行:

        if (hasQueryParams) {
            return templateUrl + window.appendCacheBustingParam;
        } else {
            return templateUrl + window.cacheBustingParam;
        }

将这些参数改为方法。

【讨论】:

  • 感谢您的意见。我想我应该更好地改写我的问题,问题是我无法在测试文件夹中注入服务。所以如果我这样做, const result = CacheBustingService .prototype .appendCacheBustingParam .call(mock, someURL);我会得到 CacheBustingService -> angular providerInjection 错误。
  • @Maria,您是在测试 app,还是端到端测试,还是仅测试此服务?如果是前者,那么您应该在例如编写测试。 selenium 来实际模拟用户与您的前端打到您的后端及以后的交互。如果是后者,那么只需导入它,存根协作者,然后用模拟调用它。在这里采取中间道路既不是很有帮助,而且(正如您发现的那样)非常困难。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-15
  • 2015-03-22
  • 2018-04-02
  • 1970-01-01
  • 2016-12-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多