Angular 1.* 无法在 karma 单元测试中访问控制器 (webpack)

Angular 1.* unable to access controller in karma unit test (webpack)

我正在尝试在 karma 中设置单元测试来测试 angular 1.* 控制器。每次我 运行 我得到的代码

[ng:areq] Argument 'MoviesListCtrl' is not a function, got undefined

当我检查控制器的模块似乎已加载时,我不确定为什么它没有加载。我的项目可以在这里找到..

我的项目在 bitbucket 上可用

https://bitbucket.org/LAD500/movies-angular-webpack/src

运行 测试..

npm install
npm test

如有任何帮助,我们将不胜感激。

我正在处理的文件是..

测试 - https://bitbucket.org/LAD500/movies-angular-webpack/src/b007e3bced7f3f6249a1b577dc83aa348490d608/test/public/js/app/services/movieslisting.spec.js

import '../../../../../src/js/app/services/movieslisting/';
import '../../../../../src/js/app/directives/movieslist/movieslistctrl';
import '../../../../../src/js/app/browserapp.js';

import {expect} from 'chai';

let createCtrl, scope, moviesListing;

beforeEach(angular.mock.module('BrowserApp'));

beforeEach(inject(($rootScope, $controller)=>{
    moviesListing = angular.injector(['ng', 'BrowserApp']).get("moviesListing");
    scope = $rootScope.$new();
    createCtrl = ()=>{
        return $controller('MoviesListCtrl', {
            $scope: scope,
            moviesListing: moviesListing
        });
    };
}));

describe('MoviesListCtrl', ()=>{

    it('placeholder test', ()=>{
        let ctrl = createCtrl();
        expect(1).to.equal(1);
    });
});

控制器

import app from '../../browserapp';

let controllerName = 'MoviesListCtrl';

app.controller('MoviesListCtrl', ['$scope', 'moviesListing', function($scope, moviesListing) {

    $scope.moviesList = {
        moviesFilter: 'costLowToHigh',
        movies: moviesListing.movieCollection
    };

    $scope.createMovieHeader = movie =>{
        let prefix = `${movie.title} (${movie.category}`;
        return movie.subcategory ? `${prefix}/${movie.subcategory})` : `${prefix})`;
    };

    $scope.updateFilter = ()=>{
        moviesListing.sortMovies($scope.moviesList.moviesFilter);
    };
    
}]);

export default controllerName;

服务是一个依赖项

import app from '../../browserapp';

let factoryName = 'moviesListing';

app.factory(factoryName, [function() {
    let movieCollection = [];

    let currentSortKey = 'costLowToHigh';

    let costLowToHigh = (a, b)=>{
        if (a.castListTotalCost > b.castListTotalCost) {
            return 1;
        }
        if (a.castListTotalCost < b.castListTotalCost) {
            return -1;
        }
        return 0;
    };
    let costHighToLow = (a, b)=>{
        if (a.castListTotalCost < b.castListTotalCost) {
            return 1;
        }
        if (a.castListTotalCost > b.castListTotalCost) {
            return -1;
        }
        return 0;
    };

    let sortFunctionsLookup = {
        costLowToHigh,
        costHighToLow
    };

    let castListTotalCost = movie => movie.actors.reduce((total, actor) => total +  actor.salary, 0);

    let addMovie = (movie)=>{
        movie.castListTotalCost = castListTotalCost(movie);
        movieCollection.push(movie);
        movieCollection.sort(sortFunctionsLookup[currentSortKey]);
    };

    let sortMovies = (sortKey)=>{
        currentSortKey = sortKey;
        movieCollection.sort(sortFunctionsLookup[currentSortKey]);
    };

    let reset = ()=>{
        movieCollection.length = 0;
    };

    return {
        movieCollection,
        addMovie,
        sortMovies,
        reset
    };
}]);

export default factoryName;

应用模块

import * as angular from 'angular';

var app = angular.module('BrowserApp', []);

app.init = ()=>{
    angular.element(document).ready(function() {
        angular.bootstrap(document, ['BrowserApp']);
    });
};

export default app;

业力配置

module.exports = function(config) {
  config.set({

    basePath: '',

    frameworks: ['mocha', 'es6-shim'],

    files: [
      './node_modules/angular/angular.js',
      './node_modules/angular-mocks/angular-mocks.js',
      'test/**/*spec.js'
    ],

    preprocessors: {
      'test/**/*spec.js': ['webpack', 'sourcemap']
    },

    reporters: ['progress'],

    port: 9876,

    colors: true,

    logLevel: config.LOG_INFO,

    autoWatch: false,

    browsers: ['PhantomJS'],

    singleRun: true,

    concurrency: Infinity,

    webpack: {
      devtool: 'inline-source-map',
      module: {
        loaders: [
          {test: /\.js$/, exclude: /node_modules/, loader:"babel-loader"},
          { test: /\.html$/, loader: "html" }
        ]
      },
      htmlLoader: {
        attrs: false
      }
    },

    webpackMiddleware: {
      noInfo: true
    }

  })
}

我自己设法解决了这个问题。

诀窍是使用 javascript 文件为您的测试生成一个包

javascript 文件,specs.karma.js 看起来像这样..

import 'angular';
import 'angular-mocks/angular-mocks';

const testsContext = require.context('./', true, /.spec$/);
testsContext.keys().forEach(testsContext);

业力配置..

module.exports = function karmaConfig (config) {
  config.set({
    logLevel: config.LOG_INFO,

    client: { captureConsole: true },

    frameworks: ['mocha', 'es6-shim'],

    reporters: ['progress'],

    files: ['./src/js/specs.karma.js'],

    preprocessors: {
      './src/js/specs.karma.js': ['webpack', 'sourcemap']
    },

    browsers: [ 'PhantomJS'],

    singleRun: true,

    webpack: require('./webpack.test.config'),

    webpackMiddleware: {
      noInfo: 'errors-only'
    }
  });
};

还有 webpack.test.config.js..

module.exports = {
  devtool: 'inline-source-map',
  module: {
    loaders: [
      {test: /\.js$/, exclude: /node_modules/, loader:"babel"},
      { test: /\.html$/, loader: "html" }
    ]
  },
  htmlLoader: {
    attrs: false
  }
}