"错误:与Karma + RequireJS + Jasmine不匹配的匿名define()"

rob*_*ash 8 javascript requirejs jasmine angularjs karma-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');
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

然后我有一个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'
    ],

  });
};
Run Code Online (Sandbox Code Playgroud)

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();
  },
});
Run Code Online (Sandbox Code Playgroud)

最后一个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(); });
}
Run Code Online (Sandbox Code Playgroud)

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

但是我被困Error: Mismatched anonymous define()在了这里tests/user/user.test.js,我看不出有什么问题.这是输出:http: //pastebin.com/evJPj9B3

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

define('namedtestorso', ['angular', 'angular-mocks', 'app'], function(angular, app) {
  ...
Run Code Online (Sandbox Code Playgroud)

...我不再收到错误,但测试没有执行.由于我可以回想起所有的例子都使用它作为匿名定义我假设命名在这里不正确.但在这种情况下,执行日志输出显示配置回调来自main.test.js执行两次.(这是暗示某事吗?)

如果有人知道如何解决它/让它运行,甚至如何继续发现什么是错的,那将会很棒.提前致谢!

rob*_*ash 10

我现在运行它,所以将我的解决方案留在这里:

我想我现在理解得有点好了karma(请告诉我,如果我错了),所以找到了我必须要做的事情.

它似乎都是关于将文件放入其中karma.conf.js以便它们可用于main.test.js加载.否则它们不在"上下文"中,无法访问.但是当放入那里时,请确保将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 }
  ...
Run Code Online (Sandbox Code Playgroud)

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

解决了这个问题后,其他一些模块找不到.因为我使用了RequireJS优化器,所以我必须将所有模块"映射"到主app.js文件中,这样当测试JS文件需要某个模块时,RequireJS可以确保它被(或得到)加载.

所以我最后更改了以下paths部分main.test.js:

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

对,这似乎有点hacky.在解决此问题的同时,我还将工作流程更改为在dev文件上运行单元测试,并依赖其他工具正常工作(如果没有问题可以通过e2e测试捕获).

希望在我的情况下帮助别人!