【问题标题】:Jasmine testing with AngularJS, Object [object Object] has no method applyJasmine 使用 AngularJS 测试,Object [object Object] 没有方法 apply
【发布时间】:2013-08-21 08:19:17
【问题描述】:

在我的新项目中,我一直在摆弄 AngularJS 和 Jasmine。我在 Jasmine 方面有相当丰富的经验,但之前没有将它与 AngularJS 结合使用。我正在尝试编写一个非常非常简单的单元测试,但我无法让它工作。我只是根据文档做一个非常简单的测试:

describe("Controller tests", function () {

    describe("LoginController", function () {

        var scope = {};

        beforeEach(inject(function ($rootScope, $controller) {
            scope = $rootScope.$new();
            $controller(LoginController, {
                $scope: scope
            });
        }));

        it("should prepare the login page", function () {
            scope.prepareLoginPage();
        });

    });

});

但是,它根本不起作用。 LoginController 是一个非常基本的函数,没有什么特别之处。当我尝试 Jasmine HTML 运行器时,我得到以下输出:

TypeError: Object [object Object] has no method 'apply'
TypeError: Object [object Object] has no method 'apply'
    at jasmine.Block.execute (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:1064:23)
    at jasmine.Queue.next_ (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2096:37)
    at jasmine.Queue.start (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2049:10)
    at jasmine.Spec.execute (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2376:16)
    at jasmine.Queue.next_ (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2096:37)
    at jasmine.Queue.start (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2049:10)
    at jasmine.Suite.execute (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2521:16)
    at jasmine.Queue.next_ (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2096:37)
    at jasmine.Queue.start (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2049:10)
    at jasmine.Suite.execute (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2521:16)
TypeError: Cannot call method 'prepareLoginPage' of undefined
TypeError: Cannot call method 'prepareLoginPage' of undefined
    at null.<anonymous> (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/angularjs/seabirds/controllersTest.js:18:29)
    at jasmine.Block.execute (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:1064:23)
    at jasmine.Queue.next_ (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2096:37)
    at jasmine.Queue.start (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2049:10)
    at jasmine.Spec.execute (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2376:16)
    at jasmine.Queue.next_ (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2096:37)
    at jasmine.Queue.start (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2049:10)
    at jasmine.Suite.execute (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2521:16)
    at jasmine.Queue.next_ (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2096:37)
    at jasmine.Queue.start (file:///Users/geroen_joris/Development/Source/LifeWatchINBO/SeaBirds/src/test/javascript/lib/jasmine-1.3.1/jasmine.js:2049:10)

问题似乎出在 beforeEach() 中,因为它会接受的唯一语法是:

beforeEach(function() { ... });

但即使我引入了这个(这与AngularJS documentation 矛盾),控制器和范围仍然没有初始化。有人指点一下吗?

我正在使用 Jasmine 1.3.1 和 AngularJS 1.0.7。

【问题讨论】:

  • $controller 绑定在哪里?
  • 我犯了一个错误,传递了文字“LoginController”,而不是函数 ()。现在,我将函数传递给 $controller ...但仍然不是香蕉. @DavinTryon 你能详细说明一下吗?你的意思是,我应该将 $controller 绑定到变量吗?
  • 啊,我想我明白你的意思了。我现在在inject() 内的函数中传递$controller。不过还是没有运气:(
  • 是的,我就是这个意思。

标签: javascript unit-testing testing angularjs jasmine


【解决方案1】:

显然LoginController 没有在 jasmine 的规范范围内定义。 您应该在应用程序的模块中定义您的控制器:

angular.module("myApp, []).controller("LoginController", function($scope) {});

..并在规范中使用$controller("LoginController", {}) 实例化它。

【讨论】:

  • 根据您的建议,我做了一些修改: - 在 controllers.js 我添加了这些行: var app = angular.module("seaBirds", [], function () {}); app.controller("LoginController", function ($scope, $http) { ... - in controllersTest.js var scope; var ctrl; beforeEach(angular.module("seaBirds")); beforeEach(inject(function ($ rootScope, $controller) { scope = $rootScope.$new(); ctrl = $controller('LoginController', { $scope: scope, $http: {} }); })); 但还是没有运气...
  • 对不起,糟糕的代码,似乎无法正确格式化。但是 LoginController 在 jasmine 规范范围内定义的,它一直都是。
  • 检查这个项目github.com/9ci/angle-grinder/tree/master/app/scripts/…也许它会让你知道应该如何在茉莉花的规范中定义和访问控制器。
  • 我以前没有使用过 CoffeeScript,但据我所知,您的设置与我现在的设置相同。基本上:(1)你有一个模块定义; (2) 向该模块添加控制器; (3) 你做一个 beforeEach(angular.module(); (4) 你做一个注入(...),在那里你实例化控制器。据我所知,我们的设置是完全一样的,尽管我使用的是“常规” JavaScript :) 该死的,从没想过我会这么卡,只是写了一个基本的测试......
【解决方案2】:

好的,我知道出了什么问题。我假设您可以像运行任何其他 Jasmine 测试一样运行测试,这意味着:使用 SpecRunner.html 文件。

然而,这不是真的。您只能使用 Karma 运行 AngularJS 测试。虽然这看起来合乎逻辑,但老实说,我发现它确实不合逻辑。 最重要的一点是,您甚至看到您正在加载一个 JASMINE_ADAPTER(在您的 karma 配置文件中),它基本上覆盖了 Jasmine 测试框架的一部分。老实说,我发现这是一个非常糟糕的解决方案,并且与 AngularJS 团队的预期不同。如果您开始像他们那样覆盖框架的内部,那么您正在寻找解决方案,即从长远来看,这不是一条你想走的路。

我已经写了一段时间的 JS 测试,发现 Jasmine 非常轻量级,并且易于实现。我之前的项目之一,我们使用了 KnockoutJS。我当时实现了 Jasmine,以便能够为 JS 做 TDD。这很容易,而且效果很好。 因此,对于这项任务,我选择使用 AngularJS 作为一种技术,因为在稍微摆弄了一下之后,我对它的工作方式非常感兴趣。我承认,我没有尝试编写单元测试,因为它们都是基于 Jasmine 的,而且看起来很简单。就我而言,重要的经验教训。

现在,我需要安装 Node.JS、Karma 和 PhantomJS 才能在我们的构建服务器上运行这些测试。

在我的书中,AngularJS 只是丢了很多分。我什至怀疑整个测试设置的投资是否值得选择框架。我承认,AngularJS 在许多层面上都优于许多竞争对手——但没有什么,而且真的没有什么比能够编写经过全面测试的软件(最好是 TDD 风格)更重要。哦,是的,Karma 似乎是炸弹,所有目录的自动检查等等 - 但想想看:你需要拖入它的所有依赖项(这不是微不足道的)才能使用它。 Pure Jasmine 开箱即用,在 Maven 构建中无头,配置最少。

哼哼。无感。

【讨论】:

  • ..这真的很奇怪。在我的项目中,我能够从控制台(通过业力)和通过 jasmine spec runner 运行 jasmine 规范,没有任何问题。肯定是你的代码有问题。
  • @luacassus:不,代码没有问题。不可能,我没有任何代码,我只是写了一个非常基本的测试(只有注入功能)。我只能通过 Karma 运行我的 AngularJS 测试。好吧,据说,如果我将 JASMINE_ADAPTER 加载到 SpecRunner.html 中,它可能会起作用 - 目前还没有尝试过,但无论如何我都在使用 Karma。顺便说一句:为了完成这一切,这也是 Karma 跑步者要考虑的事情:stackoverflow.com/questions/14762605/…。万岁,有据可查的解决方案。
  • AngularJS 是由谷歌开发的。当然,他们不会正确扩展文档。 AngularJS 有很多扩展,因为在没有大量额外基础代码的情况下,基本代码无法流畅地涵盖大部分您想用它做的事情。以 Angular-UI-Grid 为例。大量数据,组织和呈现精美,但仍需要大量后端工作才能使单元格/行可点击...github.com/angular-ui/ui-grid/issues/2228#issuecomment-73802274。仍在进行中...谢谢,C§
猜你喜欢
  • 1970-01-01
  • 2013-06-03
  • 2016-01-03
  • 1970-01-01
  • 2015-06-09
  • 1970-01-01
  • 2013-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多