"Error: Mismatched anonymous define()" with Karma + RequireJS + Jasmine

"Error: Mismatched anonymous define()" with Karma + RequireJS + Jasmine

我现在被困了一段时间,试图设置和运行单元测试。

我有一个 AngularJS 前端加载了 RequireJS 并且 r.js 针对生产进行了优化,所以它很好地放在一个文件中。这有效!

执行单元测试不起作用。到目前为止这没什么特别的,只是从教程中复制了一个启动器。

tests/user/user.test.js:

define(['angular', 'angular-mocks', 'app'], function(angular, app) {
  describe('Unit: UserController', function() {
    beforeEach(module('user.app'));

    it('should do something', function() {
      console.log('did it');
    });
  });
});

然后我有一个karma.conf.js:

module.exports = function(config) {
  config.set({
    logLevel: config.LOG_DEBUG,
    basePath: './',

    files: [
      // r.js'd app files
      {pattern: 'dist/app.js', included: false},
      // the tests
      {pattern: 'tests/**/*.test.js', included: true},
    ],

    excluded: ['tests/main.test.js']

    frameworks: ['jasmine', 'requirejs'],

    browsers: ['PhantomJS'],

    plugins: [
      'karma-jasmine',
      'karma-junit-reporter',
      'karma-phantomjs-launcher',
      'karma-requirejs'
    ],

  });
};

A main.test.js:

var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;

var pathToModule = function(path) {
  var returnValue = path.replace(/^\/base\//, '').replace(/\.js$/, '');
  return returnValue;
};

Object.keys(window.__karma__.files).forEach(function(file) {
  if (TEST_REGEXP.test(file)) {
    // Normalize paths to RequireJS module names.
    allTestFiles.push(pathToModule(file));
  }
});

require.config({
  baseUrl: '/base',

  paths: {
    'angular-mocks': 'node_modules/angular-mocks/angular-mocks',
    'app': 'dist/app',
  },

  deps: allTestFiles,

  callback: function() {
    console.log('load complete');
    window.__karma__.start();
  },
});

最后是 gulp 任务:

var gulp  = require('gulp');
var karma = require('karma').server;

gulp.task('unit-test', function(done) {
  karma.start({
    configFile: __dirname + '/karma.conf.js',
      singleRun: true
   }, function() { done(); });
}

我在这里和那里添加了一些日志输出,它显示文件已加载。

但我无法在 tests/user/user.test.js 中得到这个 Error: Mismatched anonymous define(),我看不出有什么问题。这是输出: http://pastebin.com/evJPj9B3

如果我将单元测试模块命名为

define('namedtestorso', ['angular', 'angular-mocks', 'app'], function(angular, app) {
  ...

...我不再收到错误,但未执行测试。由于我记得的所有示例都将其用作匿名定义,因此我假设此处的命名不正确。但在那种情况下,执行的日志输出显示来自 main.test.js 的配置回调被执行了两次。 (这是什么暗示吗?)

如果有人知道如何修复 it/get 它 运行 甚至如何继续找出问题所在,那就太好了。提前致谢!

我现在明白了 运行 所以我会在这里留下我的解决方案:

我想我现在对 karma 的工作原理有了更好的理解(如果我错了请告诉我),所以找到了我必须做的事情。

这似乎就是将文件放入 karma.conf.js 以便它们可供 main.test.js 加载。否则它们在 "context" 之外,无法访问。但是当放在那里时,一定要将 included 标志设置为 false.

karma.conf.js 的更改:

files: [
  ...
  // Also included these dependencies. All the others are minified in the
  // app.js but if you don't do that, also include all project deps like
  // AngularJS etc.
  { pattern: 'node_modules/jasmine-core/lib/jasmine-core/boot.js', included: false },
  { pattern: 'node_modules/angular-mocks/angular-mocks.js', included: false},

  // Then I had an error in my pattern ('tests/**/*.test.js')
  // Only the `main.test.js` is supposed to be included!
  { pattern: 'tests/user/user.test.js', included: false }
  { pattern: 'tests/main.test.js', included: true }
  ...

如果我是正确的,Karma 会创建一个 HTML 文件,带有 included: true 的文件将通过脚本标签加载。这就是为什么如果使用 RequireJS,将 include 设置为 false 很重要,因为如果这样做,您将获得 Error: Mismatched anonymous define()。所以这对我来说很有意义。

解决了这个问题后,其他一些没有找到的模块。因为我使用了 RequireJS 优化器,所以我必须 "map" 我所有的模块到主 app.js 文件,这样当测试 JS 文件需要某个模块时,RequireJS 可以确保它是(或获取)已加载。

所以我最终更改了 main.test.js 中的 paths 部分:

paths: {
  // Added these for example
  'angular': '../dist/app',
  'angular-ui-router': '../dist/app',
  // (and also my project modules)
  ...

对,这似乎有点老套。与此同时,在解决这个问题后,我还将我的工作流程更改为 运行 对开发文件进行单元测试,并依靠其他工具正常工作(如果没有问题,则由 e2e 测试捕获)。

希望对遇到我情况的人有所帮助!

确切地说,如果你去 requirejs 网站,这个错误说明你是否在 html 中包含了任何脚本标签,这意味着 html 由 karma

提供

因此在 karma.conf.js 中,当您包含以下文件时: files['/base/src/scripts/xyz.js'] 在我看来,它是作为脚本标签添加的,你会继续获取 错误:不匹配的匿名 define() 模块

try pattern example:{pattern: '/base/src/scripts/xyz.js', included: false} 阻止在脚本标签中添加 js