Angularjs 控制器函数上的类型错误`

Angularjs 控制器函数上的类型错误`,angularjs,jasmine,Angularjs,Jasmine,我正在我的控制器上运行一个测试,以确定它是否正确定义,但我在控制器对象上不断得到一个TypeError:undefined。下面是完整的错误: Search Controller should have the controller defined <<< FAILURE! * TypeError: 'undefined' is not an object (evaluating 'myMenuDataLoad.then') * Expected undefined to

我正在我的控制器上运行一个测试,以确定它是否正确定义,但我在控制器对象上不断得到一个
TypeError:undefined
。下面是完整的错误:

Search Controller
  should have the controller defined <<< FAILURE!
* TypeError: 'undefined' is not an object (evaluating 'myMenuDataLoad.then')
* Expected undefined to be defined.
我通过在参数中传递控制器所需的一切来初始化控制器,即
scope
headerService
menuService
navigationService
——我使用
jasmine.createSpyObj
方法模拟这些服务,并传入所有相关方法(控制器上使用的方法):

控制器的实际初始化发生在这里:

beforeEach(inject(function($rootScope, $injector, $controller, _headerService_, _menuService_, _navigationService_) {

    scope = $rootScope.$new();

    // Instantiate the controller
    searchController = $controller('VisibilitySearchController', {
        $scope : scope,
        headerService : headerService,
        menuService : menuService,
        navigationService : navigationService
    });
}));
那么我做错了什么?为什么考试(见下文)没有通过

it("should have the controller defined", function() {
    expect(searchController).toBeDefined();
});
我是否正确地模拟了服务?为了正确初始化局部控制器变量及其使用的方法,需要对其执行哪些操作

谢谢


更新

我已经对此进行了进一步的研究,但不幸的是仍然收到相同的未定义错误。当您创建一个服务的模拟对象时,您是否必须为该服务提供您所使用的所有依赖项和方法?例如:

 menuService = jasmine.createSpyObj('menuService', ['$parse','$q', 'dataService', 'loadData', 'then']);
    module(function($provide) {
        $provide.value('menuService', menuService);
    });
在这里,当我创建模拟对象时,我为它提供了它所期望的所有依赖项,另外我添加了两个函数,我在控制器中使用了这两个函数。 那么,如何在模拟对象中模拟函数呢?我尝试了这个,但仍然得到相同的错误:

menuService.loadData = jasmine.createSpy( 'loadData()' ).andReturn( data );

如注释中所述,您的
menuService.loadData()
将始终返回未定义的,因此计算表达式
myMenuDataLoad。然后,
将始终失败,如错误中所述。您必须做的是提供一个
menuService.loadData
的实现,它将返回一个承诺。如果您希望调用这些方法,但不依赖它的任何返回值,那么您可以按照您的方式进行模拟。如果需要该方法返回某些内容,可以通过以下方式定义
menuService

var menuService = {
    loadData: function() {  
        var deferred = $q.defer();      
        var data = []; //put any data you need here to be returned within the promise       

        deferred.resolve{data);             
        return deferred.promise;    
    }
}

module(function($provide) {
        $provide.value('menuService', menuService);
    });
spyOn(menuService, "loadData").andCallThrough()
您将需要
$q
的实例,您可以在
inject
调用中获得该实例,类似于
$rootScope
$injector

如果您想监视
menuService.load
函数,可以这样做:

var menuService = {
    loadData: function() {  
        var deferred = $q.defer();      
        var data = []; //put any data you need here to be returned within the promise       

        deferred.resolve{data);             
        return deferred.promise;    
    }
}

module(function($provide) {
        $provide.value('menuService', menuService);
    });
spyOn(menuService, "loadData").andCallThrough()

这将保持方法的模拟实现,但仍然允许您断言它已被调用等。我认为您不需要它。

在测试中,
menuService.loadData()
始终返回未定义,因此
myMenuDataLoad。然后,
语句将失败,因为
myMenuDataLoad
将未定义。你必须模仿menuService.loadData(),以返回一个承诺,该承诺将解析为一个适当的数据结果。你能通过提供一个例子来详细说明吗?谢谢你的例子,它现在让事情变得更清楚了