首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >单元测试返回TypeError:未定义不是构造函数错误消息

单元测试返回TypeError:未定义不是构造函数错误消息
EN

Stack Overflow用户
提问于 2016-09-24 18:08:48
回答 1查看 2.3K关注 0票数 0

我试着用茉莉花写一个简单的测试来测试SearchCtrl。但是,我不知道如何构造单元测试,因为这是我第一次使用它。到目前为止,我所做的就是:

services.js

代码语言:javascript
复制
function CategoryService($http) {

    this.getCategoryList = function () {

        return $http({
            method: 'GET',
            url: server + '/api/category/',
        });

    }

}

样本输出:

代码语言:javascript
复制
[
    {
        "id": "1551742a-5963-4d40-9abb-af7a6fb4ec5d",
        "category": "Coach"
    }
]

controller.js

代码语言:javascript
复制
function SearchCtrl($scope, CategoryService) {

    CategoryService.getCategoryList().then(function(dataResponse) {
        $scope.categories = dataResponse.data;
    });

}

search.controller.tests.js

代码语言:javascript
复制
describe('SearchCtrl', function() {

  var $controller, scope, categoryServiceMock;

  // TODO: Load the app module
  beforeEach(module('app.controllers'));
  beforeEach(module('app.services'));

  // TODO: Instantiate the controller and mocks
  beforeEach(inject(function($controller, categoryServiceMock) {
    scope = $rootScope.$new();

    // mock categoryService
    categoryServiceMock = {
      login: jasmine.createSpy('category spy')
    };

    // instantiate SearchCtrl
    controller = $controller('SearchCtrl', {
      $scope: scope,
      'CategoryService': categoryServiceMock
    })

  }));

  describe('#searchList', function() {

    // TODO: Call getCategoryList() on the controller
    it('should call getCategoryList on categoryService', function() {
      expect(categoryServiceMock.getCategoryList).toHaveBeenCalledWith('Coach');
    });

    describe('once the search is executed', function() {
      it('if successful, return a list of categories', function() {

        // TODO: Mock response from CategoryService
        expect(categoryServiceMock.getCategoryList).toHaveBeenCalledWith('Coach');
      });
    });
  });
});

这将返回以下错误:

代码语言:javascript
复制
Error: [$injector:unpr] Unknown provider: categoryServiceMockProvider <- categoryServiceMock

我该怎么解决呢?此外,我是否以正确的方式构造了我的单元测试?

更新25/09

我将测试更改为:

代码语言:javascript
复制
describe('SearchCtrl', function() {

  var scope;
  var CategoryServiceMock;
  var SearchCtrl;

  // Load the app module
  beforeEach(module('dingocv.controllers', ['dingocv.services']));

  // Define CategoryServiceMock
  beforeEach(function() {
    CategoryServiceMock = {
      getCategoryList: function() {}
    };
  });

  // Inject required services and instantiate the controller
  beforeEach(inject(function($rootScope, $controller) {
    scope = $rootScope.$new();
    SearchCtrl = $controller('SearchCtrl', {
      $scope: scope,
      CategoryService: CategoryServiceMock
    });
  }));

  // Tests

  describe('#searchList', function() {
    it('should call registerBook Parse Service method', function () {
      spyOn(CategoryServiceMock, 'getCategoryList').andCallThrough();
      scope.getCategoryList();
    })
  });

});

我现在得到了这个错误:

代码语言:javascript
复制
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 0 of 1 SUCC
PhantomJS 2.1.1 (Windows 8 0.0.0) SearchCtrl #searchList should call registerBook Parse Service method FAILED
        forEach@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:13691:24
        loadModules@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17878:12
        createInjector@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17800:30
        workFn@D:/myapp-mobile/www/lib/angular-mocks/angular-mocks.js:3074:60
        loaded@http://localhost:9876/context.js:151:17
        D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17918:53
        TypeError: undefined is not a constructor (evaluating 'spyOn(CategoryServiceMock, 'getCategoryList').andCallThrough()') in unit-tests/search.controller.tests.js (line 30)
        unit-tests/search.controller.tests.js:30:67
        loaded@http://localhost:9876/context.js:151:17
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 (1 FPhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.04 secs / 0.021 secs)
25 09 2016 09:48:38.940:INFO [watcher]: Changed file "D:/myapp-mobile/www/tests/unit-tests/search.controller.tests.js".
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 0 of 1 SUCCPhantomJS 2.1.1 (Windows 8 0.0.0) SearchCtrl #searchList should call registerBook Parse Service method FAILED
        forEach@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:13691:24
        loadModules@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17878:12
        createInjector@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17800:30
        workFn@D:/myapp-mobile/www/lib/angular-mocks/angular-mocks.js:3074:60
        loaded@http://localhost:9876/context.js:151:17
        D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17918:53
        TypeError: undefined is not a constructor (evaluating 'spyOn(CategoryServiceMock, 'getCategoryList').andCallThrough()') in unit-tests/search.controller.tests.js (line 30)
        unit-tests/search.controller.tests.js:30:67
        loaded@http://localhost:9876/context.js:151:17
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 (1 FPhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.035 secs / 0.007 secs)
25 09 2016 09:48:42.307:INFO [watcher]: Changed file "D:/myapp-mobile/www/tests/unit-tests/search.controller.tests.js".
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 0 of 1 SUCCPhantomJS 2.1.1 (Windows 8 0.0.0) SearchCtrl #searchList should call registerBook Parse Service method FAILED
        forEach@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:13691:24
        loadModules@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17878:12
        createInjector@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17800:30
        workFn@D:/myapp-mobile/www/lib/angular-mocks/angular-mocks.js:3074:60
        loaded@http://localhost:9876/context.js:151:17
        D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17918:53
        TypeError: undefined is not a constructor (evaluating 'spyOn(CategoryServiceMock, 'getCategoryList').andCallThrough()') in unit-tests/search.controller.tests.js (line 30)
        unit-tests/search.controller.tests.js:30:67
        loaded@http://localhost:9876/context.js:151:17
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 (1 FPhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.069 secs / 0.008 secs)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-25 09:46:04

你只是让你的测试变得复杂了所有的注射。下面是一个适用于您的案例的简单示例:

服务模块

代码语言:javascript
复制
angular.module('dingocv.services', [])
.service('CategoryService', ['$http', function CategoryService($http) {
    this.getCategoryList = function () {
        //Wasn't sure what server was here. So created a variable here. Feel free to change this.
        var server = 'https://www.example.com';
        return $http({
            method: 'GET',
            url: server + '/api/category/',
        });
    }
}]);

控制器模块

代码语言:javascript
复制
angular.module('dingocv.controllers', ['dingocv.services'])
.controller('SearchCtrl', ['$scope', 'CategoryService', function SearchCtrl($scope, CategoryService) {
    CategoryService.getCategoryList().then(function(dataResponse) {
        $scope.categories = dataResponse.data;
    });
}]);

测试

代码语言:javascript
复制
describe('SearchCtrl', function() {
    var response;
    response = {
        status: 200,
        data: [{
            "id": "1551742a-5963-4d40-9abb-af7a6fb4ec5d",
            "category": "Coach"
        }]
    };

    //Injecting the modules that would then be used in the tests
    beforeEach(module('dingocv.services'));
    beforeEach(module('dingocv.controllers'));

    beforeEach(inject(function($controller, $rootScope, _CategoryService_) {
        $scope = $rootScope.$new();
        CategoryService = _CategoryService_;

        //Creating a spy for this method so that it doesn't call the original Service method.
        spyOn(CategoryService, 'getCategoryList').and.callFake(function(){
            return{
                then: function(successCallback){
                    successCallback(response);
                }
            }
        });

        SearchCtrl = $controller('SearchCtrl', {
            $scope: $scope
        });
    }));

    describe('Initialization', function() {
        it('should initialize the controller\'s scope with categories', function(){
            expect(CategoryService.getCategoryList).toHaveBeenCalled();
            expect($scope.categories).toBeDefined();
            expect($scope.categories.length).toEqual(1);
            expect($scope.categories[0].id).toEqual(response.data[0].id);
            expect($scope.categories[0].category).toEqual(response.data[0].category);
        });
    });
});

希望这能有所帮助。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39679471

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档