未捕获错误:不匹配的匿名define()模块:使用requirejs进行karma和jasmine单元测试时的函数

时间:2017-08-22 11:27:32

标签: angularjs unit-testing jasmine requirejs karma-jasmine

我正在尝试为我的控制器运行单元测试用例,我尝试了以下但是得到以下错误,请让我知道成功运行此测试。提前谢谢。

spec.js:

describe('MainCtrl', function() {
  beforeEach(module('app-module'));
  var $controller;
  beforeEach(inject(function(_$controller_){ 
    $controller = _$controller_;
  }));

  describe('$scope.titleofapp', function() {
    var $scope, controller;
    beforeEach(function() {
      $scope = {};
      controller = $controller('MainCtrl', { $scope: $scope });
    });

    it('sets the title of app to "app-module" module', function() {
      $scope.titleofapp();
      expect($scope.title).toEqual('My Test App !');
    });
  });
});

app.js:

define(['angular', './app-module'], function(angular, appModule) {
    'use strict';
    return appModule.controller('MainCtrl', ['$http', '$q', 'appService', '$stateParams', function($http, $q, $stateParams, appService){
        $scope.titleofapp = function(){
        $scope.title = 'My Test App !';}
   }]);  
});

下面是我的karma.conf.js文件配置:

karma.conf.js:

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine','requirejs'],

    files: [
            'node_modules/requirejs/require.js',
            'node_modules/karma-requirejs/lib/adapter.js',
            'node_modules/angular/angular.js',
            'node_modules/angular-mocks/angular-mocks.js',
           'public/app/app.js',
           'public/tests/spec.js'
         ],

    exclude: [
    ],

    plugins: [
            'karma-requirejs',
            'karma-chrome-launcher',
            'karma-jasmine'
          ],
    preprocessors: {
    },
    reporters: ['progress'],

    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
     singleRun: false,
    concurrency: Infinity
  })
}

我已经配置了上面的requirejs并且现在得到以下错误: 错误:

    Uncaught Error: Mismatched anonymous define() module: function (angular, appModule) {
      'use strict';
    return appModule.controller('MainCtrl', ['$http', '$q', 'appService', '$stateParams', function($http, $q, $stateParams, appService){
        $scope.titleofapp = function(){
        $scope.title = 'My Test App !';}

      }]);
  }
  http://requirejs.org/docs/errors.html#mismatch
  at node_modules/requirejs/require.js:165

1 个答案:

答案 0 :(得分:0)

以下是我编辑的karma.conf.js文件,可以使用RequireJS进行运行。样式为//的评论 - 大多数(除了尾随时)我注释掉的内容,并设置为/* */ - 是关于特定行存在或不存在的目的的真实评论。我希望所有评论都有助于理解正在发生的事情。

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine','requirejs'],

    files: [
        /* not needed because you've told to use requirejs higher in frameworks */
//        'node_modules/requirejs/require.js',

        /* i assume this one in no need in your case but could be yes */
//        'node_modules/karma-requirejs/lib/adapter.js',

        /* as far as i understand angular.js is amd loadable so don't load it directly */
//        'node_modules/angular/angular.js',

        /* i am not sure about this one and how it should be launched so commented it out for now */
//        'node_modules/angular-mocks/angular-mocks.js',

        /* will be loaded by tests*/
//        'public/app/app.js',

        /* tests should not be loaded directly eigther */
//        'public/tests/spec.js'

        /* now configure karma with what will be servable */
        {pattern: 'node_modules/**/*.js', included: false}, // all stuff from what npm installed
        {pattern: 'src/**/*.js', included: false}, // your source filed
        {pattern: 'tests/**/*Test.js', included: false},    // your tests or specs

        /* this is the only file to be loaded directly */
        'tests/test-main.js' // karma will load this file and it will do all the stuff
     ],

    exclude: [
    ],

    /* karma will load all sibling npm modules with name karma-* so these lines not needed i believe */
//    plugins: [
//        'karma-requirejs',
//        'karma-chrome-launcher',
//        'karma-jasmine'
//    ],
    preprocessors: {
    },
    reporters: ['progress'],

    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false,
    concurrency: Infinity
  })
}

然后我在这里为main-test.js文件制作了示例代码。

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

// Get a list of all the test files to include
/* as far as i remember window.__karma__.files contains array of all servable files */
Object.keys(window.__karma__.files).forEach(function (file) {
    //console.log('original path', file);
    if (TEST_REGEXP.test(file)) {
        /* below i commented out file path modification suggested at http://karma-runner.github.io/1.0/plus/requirejs.html
         * personally i never needed that. Your case might be different so you can play around with this part
         */
        var normalizedTestModule = file;//'/base/' + file.replace(/^\/base\/|\.js$/g, '')
        //console.log('normalized path', normalizedTestModule);
        allTestFiles.push(normalizedTestModule);
    }
});

//console.log(allTestFiles); // list all test filed that will be run

/* now confifure requirejs so it could do the job 
 * for more details please visit http://requirejs.org/docs/api.html#config
 */
require.config({
    // Karma serves files under /base, which is the basePath from your config file
    /* i prefer this to be default */
    baseUrl: '/base/src',
    paths: {
        /* could be this to do stuff like
         * define(['node_modules/cool-module/module.js], function(Module){
         * 
         * });
         */
        node_modules: '/base/node_modules',

        /* below is just examples that what it could be if you needed those */
//        jquery: '/base/node_modules/jquery/dist/jquery',
//        underscore: '/base/node_modules/underscore/underscore',
//        backbone: '/base/node_modules/backbone/backbone',
//        text: '/base/node_modules/requirejs-text/text',
//        templates: '/base/src/templates'
    },

    /* Dynamically load all test files
     * An array of dependencies to load. Useful when require is defined as a 
     * config object before require.js is loaded, and you want to specify 
     * dependencies to load as soon as require() is defined. Using deps 
     * is just like doing a require([]) call, but done as soon as the loader 
     * has processed the configuration. It does not block any other require() 
     * calls from starting their requests for modules, it is just a way to 
     * specify some modules to load asynchronously as part of a config block.
     * (http://requirejs.org/docs/api.html#config-deps)
     */
    deps: allTestFiles,

    /*  A function to execute after deps have been loaded. Useful when require 
     * is defined as a config object before require.js is loaded, and you want 
     * to specify a function to require after the configuration's deps array 
     * has been loaded.
     * http://requirejs.org/docs/api.html#config-callback
     * Could be as simple as 
     *     callback: window.__karma__.start
     * but i do it via additional wrapper so i can require something specific 
     * for the whole test suite (like jasmine-jquery), you will the sample below
     */
    callback: startTestWithJasmineJquery
});

function startTestWithJasmineJquery(){
    require(['node_modules/jasmine-jquery/lib/jasmine-jquery'], function(){
        /* now jasmine-jquery is loaded and its features are available
         * so we can window.__karma__.start -- it will actually run tests
         */
        window.__karma__.start();
    });
}

请注意,所有配置选项都假设文件夹和一些特定文件结构为:

node_modules/
src/
tests/
    test-main.js
karma-conf.js

请再次注意,这是我提供的非常基本的配置,可能有一些与angular相关的特定内容或您的项目逻辑和需求,因此可能会有一些(或许多)更改要做。