【问题标题】:Testing Angular controller with Require and Typescript使用 Require 和 Typescript 测试 Angular 控制器
【发布时间】:2014-11-04 13:57:59
【问题描述】:

我正在尝试创建一个基本测试来验证我是否可以创建控制器或服务。

我的应用是如下目录

app/js/app.js

我的控制器在以下目录中

app/js/controllers/

这是我的 karma.conf.js 文件

        files: [
        'Scripts/jquery-2.1.1.min.js',
        'Scripts/require.js',
        'Scripts/angular.js',
        'Scripts/angular-mocks.js',
        { pattern: 'app/js/*.js', included: false },
        { pattern: 'app/js/**/*.js', included: false },
        { pattern: 'app/js/**/**/*.js', included: false },
        { pattern: 'app/js/**/**/**/*.js', included: false },
        { pattern: 'test/specs/**/*.js', included: false },
         'test/test-main.js',
    ],

    // list of files to exclude
    exclude: [
         'app/js/main.js'
    ],

test-main.js

var testFiles = [];
for (var file in window.__karma__.files) {
console.log(file);
if (/Spec\.js$/.test(file)) {
    testFiles.push(file);
}
}

requirejs.config({
paths: {
    // External libraries
    'jquery': '../../Scripts/jquery-2.1.1.min',
    'angular': '../../Scripts/angular',
    'angular-mocks': '../../Scripts/angular-mocks',
    'ngRoute': '../../Scripts/angular-route.min',
    'angular-animate': '../../Scripts/angular-animate.min',
   'angular-cookies': '../../Scripts/angular-cookies.min',

},
baseUrl: '/base/app/js',

shim: {
    'angular': {
        exports: 'angular',
        deps: ['jquery']
    },
    'angular-mocks': { exports: 'angular-mocks', deps: ['angular']  },
    'angular-animate': { exports: 'angular-animate', deps: ['angular'] },
    'ngRoute': { exports: 'ngRoute', deps: ['angular'] },
    'angular-cookies': { exports: 'angular-cookies', deps: ['angular'] },
},

  // dynamically load all test files
deps: testFiles,

  // we have to kickoff jasmine, as it is asynchronous
  callback: window.__karma__.start
});

我添加了这一行...

console.log(file)

为了确保文件被加载到

window.__karma__.files

确实如此。

测试存在于 test/specs/

define(['angular', 'angular-mocks'], (angular, ngMock: ng.IMockStatic) => {
var module = ngMock.module;
var inject: (...fns: Function[]) => any = ngMock.inject;

describe("Create an Application", function () {
    var scope, q, routeParams;
    var location;
    var app;
    beforeEach(function () {

        app = angular.module('App', []);
        inject(function ($rootScope, $q: ng.IQService, $location: ng.ILocationService) {
            scope = $rootScope;
            q = $q;
            routeParams = {};
            location = $location;
        });
    });

    it('Test Application Created', function () {
        expect(true).toBe(true);
    });
});
});

我的应用文件看起来像这样......

import angular = require('angular');
import angularRoute = require('angular-route');
import angularAnimate = require('angular-animate');
import ds = require('services/DataService');

var app = angular.module('app', [
    'ngRoute',
    'ngAnimate',
    'ngCookies',
    'kendo.directives',
    'breeze.angular',
    'ui.bootstrap'
]);

export = app;

我尝试运行测试时遇到的错误是

未能实例化模块应用程序,原因是:模块“应用程序”不可用!您要么拼错了模块名称,要么忘记加载它。

我假设它没有加载,但不确定我怎么知道。这是完成我的测试的最佳方式吗?

非常感谢任何帮助!

非常感谢!

【问题讨论】:

    标签: angularjs requirejs typescript karma-runner


    【解决方案1】:

    如果您将 Karma 与 Jasmine 一起使用,您可能会遇到 Jasmine 过于渴望的问题。

    这可以通过进行两项更改来解决,最初在我做类似事情时写的一篇文章中进行了描述,Combining TypeScript, Jasmine and RequireJS

    boot.js中你需要注释掉env.execute();方法调用:

    window.onload = function() {
        if (currentWindowOnload) {
            currentWindowOnload();
        }
        htmlReporter.initialize();
        //env.execute();
    };
    

    这是因为 window.onload 事件可能在 require.js 加载所有内容之前发生。

    一旦你加载了你需要的模块,你就可以调用:

    // Hai Jasmine - ready to go!
    jasmine.getEnv().execute();
    

    【讨论】:

    • 感谢您的输入,但在 test-main.js 文件中为 require,我有这行回调:window.__karma__.start 是否会延迟 jasmine 的启动,直到 require 加载所有内容?跨度>
    • 你可能还需要在 Jasmine 的 boot.js 文件中注释掉 env.execute();
    【解决方案2】:

    这是使用您的代码和-m amd 开关编译的内容

        describe("Create an Application", function () {
            var scope, q, routeParams;
            var controller, location;
            var route;
    
            beforeEach(function () {
                module('app', ['ngRoute', 'ngAnimate', 'ngCookies', 'kendo.directives', 'breeze.angular', 'ui.bootstrap']);
                inject(function ($rootScope, $q, $location) {
                    scope = $rootScope;
                    q = $q;
                    routeParams = {};
                    location = $location;
                });
                //   controller = new controller.ApplicationService(q, scope, route, location, _datasvc, _searchsvc);
            });
            it('Test Application Created', function () {
                expect(true).toBe(true);
            });
        });
    

    不是一个模块,它是同步的

    但是。在一个模块中工作

    define(['angular','angular-mocks'],(angular,ngMock:ng.IMockStatic)=>{
        var module = ngMock.module;
        var inject: (...fns: Function[])=>any =  ngMock.inject;
    
        describe("Create an Application", function () {
            var scope, q, routeParams;
            var  location;
            var app;
            beforeEach(function () {
    
                app = angular.module('App', []);
                inject(function ($rootScope, $q: ng.IQService, $location: ng.ILocationService) {
                    scope = $rootScope;
                    q = $q;
                    routeParams = {};
                    location = $location;
                });
            });
    
            it('Test Application Created', function () {
                expect(true).toBe(true);
            });
        });
    });
    

    或者以更 TypeScripty w/ES6esque 的方式:

        import ngMock = require('angular-mocks');
        import angular = require('angular');
        var module = ngMock.module;
        var inject: (...fns: Function[])=>any =  ngMock.inject;
    
        describe("Create an Application", function () {
            var scope, q, routeParams;
            var  location;
    
            beforeEach(function () {
                var app = angular.module('app', []);
                inject(function ($rootScope, $q: ng.IQService, $location: ng.ILocationService) {
                    scope = $rootScope;
                    q = $q;
                    routeParams = {};
                    location = $location;
                });
            });
            it('Test Application Created', function () {
                expect(true).toBe(true);
            });
        });
    

    检查您是否像在脚本标签中一样加载角度
    'files:[Scripts/angular.js',... , 这就是为什么你得到 WARNING:tried load angular more than once 把它放在{pattern: 'Scripts/angular.js', included: false ...], 您需要计算出 requirejs.confg 直到满足 deps 链。按顺序排列。这就是您设置 shim 配置的原因之一 'angular-mocks': { exports: 'angular-mocks', deps: ['angular'] },
    所以当需要角度模拟时,也需要角度, 看看 [this github repo](https://github.com/tnajdek/angular-requirejs- 种子), ...一旦您在规范中将实例附加到 angular.module /mock.module ,请再次检查史蒂夫的答案, 如果您找不到 boot.js ,您可能正在使用与 Karma 适配器捆绑在一起的 jasmine。在这种情况下,它应该可以工作,因为您已经整理了 require test-maiin.js / config / "NG_DEFER_BOOTSTRAP!" /resumeBootstrap 故事

    【讨论】:

    • 感谢您的反馈,我认为您为我指明了正确的方向,但我仍然收到错误无法读取第 2 行未定义的属性“模块”,即 var module = ngMock.module ;
    • 检查我是否需要在我的 'test-main.js' 上配置的 'angular-mocks' ,你称之为 'angularMocks' ,它应该导出 angular.mock
    • 是的,我注意到了,并更改了我的命名以匹配你的。我用我所做的更新更新了我的问题。我还附上了 grunt 的输出。再次感谢你的帮助。我会很高兴得到这个工作!
    • 添加了 cmets。我希望它有帮助:)
    • 感谢您的意见,我必须在另一个项目上工作几天,所以我不得不把它记下来。我将查看 github 链接并将其与我的项目进行比较。我确实有一个问题要问你……什么是“……fns”我以前从未见过。感谢你的帮助!我会在下周向您通报我的进展情况。
    猜你喜欢
    • 2014-06-04
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    • 2017-02-24
    • 1970-01-01
    • 2018-09-29
    • 2015-07-09
    • 1970-01-01
    相关资源
    最近更新 更多