使用jasmine和spyOn的AngularJS测试控制器给出错误'method undefined'

时间:2016-03-01 12:53:57

标签: javascript angularjs unit-testing testing jasmine

所以我正在使用Jasmine为angularJS中的应用程序编写单元测试。

我有一个带有“init”方法的控制器,它调用“secondMethod”和“thirdMethod”

我想用jasmine spyOn测试是否正确调用了“secondMethod”。

我的控制器看起来像这样:

function init() {
    secondMethod().then(function () {
        thirdMethod();
    });
}

init();

function secondMethod(){
    //do something
}

function thirdMethod(){
    //do something
}

我的测试文件如下所示:

describe("nameOfTheController", function () {
var $rootScope,
    $controller,
    $scope,
    controller;

beforeEach(function () {

    angular.mock.module("myModule");

    inject(function (_$controller_, _$rootScope_) {
        $rootScope = _$rootScope_;
        $controller = _$controller_;
        $scope = $rootScope.$new();
        controller = $controller('nameOfTheController', {
            '$scope': $scope
        });
    });
});

describe("init", function(){
    it('should run secondMethod', function(){
        spyOn(controller, 'secondMethod');
        expect(controller.secondMethod).toHaveBeenCalled();
    });
    it('should run thirdMethod', function(){
        spyOn(controller, 'thirdMethod');
        expect(controller.thirdMethod).toHaveBeenCalled();
    });

正如你所看到的,我在beforeEach中注入了控制器但是我得到错误,方法“secondMethod”和“thirdMethod”没有定义,我不太清楚为什么。

我也试过做类似以下的事情,但无济于事

控制器:

var vm = this;
vm.init = function() {
    vm.secondMethod().then(function () {
        vm.thirdMethod();
    });
}

vm.init();

vm.secondMethod = function(){
    //do something
}

vm.thirdMethod = function(){
    //do something
}

testfile的:

describe("nameOfTheController", function () {
var $rootScope,
    $controller,
    $scope,
    controller;

beforeEach(function () {

    angular.mock.module("myModule");

    inject(function (_$controller_, _$rootScope_) {
        $rootScope = _$rootScope_;
        $controller = _$controller_;
        $scope = $rootScope.$new();
        controller = $controller('nameOfTheController', {
            '$scope': $scope
        });
    });
});

describe("init", function(){
    it('should run secondMethod', function(){
        spyOn(controller, 'secondMethod');
        expect(controller.secondMethod).toHaveBeenCalled();
    });
    it('should run thirdMethod', function(){
        spyOn(controller, 'thirdMethod');
        expect(controller.thirdMethod).toHaveBeenCalled();
    });

有谁知道为什么第二种和第三种方法未定义?

修改

当使用“vm”作为前缀时,第二个和第三个方法返回undefined的原因。是在第二和第三种方法定义之前,init函数被称为

将init的调用移到第二个和第三个方法定义之下解决了问题。现在我遇到的问题是,间谍希望调用该方法但不会被调用

var vm = this;
vm.init = function() {
    vm.secondMethod().then(function () {
        vm.thirdMethod();
    });
}

vm.secondMethod = function(){
    //do something
}

vm.thirdMethod = function(){
    //do something
}

vm.init();

1 个答案:

答案 0 :(得分:0)

控制器在beforeEach()启动,即init() => seconMethod(),而你只在it()区块内窥探它。

另一方面,你之前不能窥探,因为你没有控制器对象。

IMO,解决方案是修改代码并明确调用init():

it('should run secondMethod', function() {
    spyOn(controller, 'secondMethod');
    expect(controller.secondMethod).not.toHaveBeenCalled();
    controller.init();
    expect(controller.secondMethod).toHaveBeenCalled();

});

https://jsfiddle.net/ronapelbaum/v9vyLpws/