我们如何测试非范围角度控制器方法?

Posted

技术标签:

【中文标题】我们如何测试非范围角度控制器方法?【英文标题】:How can we test non-scope angular controller methods? 【发布时间】:2014-05-20 05:32:56 【问题描述】:

Angular 控制器中的方法很少,它们不在作用域变量上。

有谁知道,我们如何在 Jasmine 测试中执行或调用这些方法?

这里是主要代码。

var testController = TestModule.controller('testController', function($scope, testService)


function handleSuccessOfAPI(data) 
    if (angular.isObject(data))
    
       $scope.testData = data;
    


function handleFailureOfAPI(status) 
    console.log("handleFailureOfAPIexecuted :: status :: "+status);


 // this is controller initialize function.
 function init() 
    $scope.testData = null; 

    // partial URL
    $scope.strPartialTestURL = "partials/testView.html;

    // send test http request 
    testService.getTestDataFromServer('testURI', handleSuccessOfAPI, handleFailureOfAPI);


 init();

现在在我的 jasmine 测试中,我们正在传递“handleSuccessOfAPI”和“handleFailureOfAPI”方法,但这些都是未定义的。

这里是茉莉测试代码。

describe('Unit Test :: Test Controller', function() 
var scope;
var testController;

var httpBackend;
var testService;


beforeEach( function() 
    module('test-angular-angular');

    inject(function($httpBackend, _testService_, $controller, $rootScope) 

        httpBackend = $httpBackend;
        testService= _testService_;

        scope = $rootScope.$new();
        testController= $controller('testController',  $scope: scope, testService: testService);
            );
);

afterEach(function() 
       httpBackend.verifyNoOutstandingExpectation();
       httpBackend.verifyNoOutstandingRequest();
    );

it('Test controller data', function () 
    var URL = 'test server url';

    // set up some data for the http call to return and test later.
    var returnData =  excited: true ;

    // create expectation
    httpBackend.expectGET(URL ).respond(200, returnData);

    // make the call.
    testService.getTestDataFromServer(URL , handleSuccessOfAPI, handleFailureOfAPI);

    $scope.$apply(function() 
        $scope.runTest();
    );

    // flush the backend to "execute" the request to do the expectedGET assertion.
    httpBackend.flush();

    // check the result. 
    // (after Angular 1.2.5: be sure to use `toEqual` and not `toBe`
    // as the object will be a copy and not the same instance.)
    expect(scope.testData ).not.toBe(null);
);
);

【问题讨论】:

【参考方案1】:

我知道这是一个旧案例,但这是我正在使用的解决方案。

使用控制器的“this”

.controller('newController',['$scope',function($scope)
    var $this = this;
    $this.testMe = function(val)
        $scope.myVal = parseInt(val)+1;
    
]);

这是测试:

describe('newDir', function()
var svc, 
    $rootScope,
    $scope,
    $controller,
    ctrl;


 beforeEach(function () 
    module('myMod');
 );

 beforeEach(function () 
    inject(function ( _$controller_,_$rootScope_) 

        $controller = _$controller_;
        $rootScope = _$rootScope_;
        $compile = _$compile_;
        $scope = $rootScope.$new();
        ctrl = $controller('newController', '$rootScope': $rootScope, '$scope': $scope );
    );
);

it('testMe inc number', function() 

    ctrl.testMe(10)
    expect($scope.myVal).toEqual(11);
);

);

Full Code Example

【讨论】:

您使用$this 是有原因的还是仅仅因为您不喜欢使用self 等变量? 你是在问为什么我将变量命名为“$this”而不是命名为“self”?我没有理由选择变量名。 “自我”可以使代码更易于阅读。 是的,确实是这个问题,谢谢 +1,优秀的解决方案。另外,请好好阅读 this$scope:***.com/a/14168699/3123195 感谢@TheDIMMReaper!也感谢您的链接,好东西。【参考方案2】:

您将无法访问这些功能。当你定义一个命名的 JS 函数时,就像你要说的一样

var handleSuccessOfAPI = function();

在这种情况下,很清楚 var 仅在块内的范围内,并且没有来自包装控制器的外部引用。

任何可以被离散调用(并因此被测试)的函数都将在控制器的 $scope 上可用。

【讨论】:

正确。此外,我们不应该测试私有函数。通常,init() 使用模拟数据进行单元测试,这将确保调用handleSuccessOfAPIhandleFailureOfAPI。模拟对象/数据应该驱动执行路径。 我认为 $scope 将函数/变量公开(将其与 Java 之类的东西进行比较时)。我对 Java 中的单元测试并不太熟悉,但是“不测试私有函数”是您通常在 Java 中所做的吗? 克里斯,我写测试的经验也很有限,写过一些 JUnit 测试,但我绝不是测试或任何方面的专家。我想,由于在实例化对象实例时未公开私有函数,因此您仍然处于只能测试可公开访问的那些事物的相同约束之下。我认为最终这是有道理的,因为当您编写测试时,您真的关心以某种黑盒方式完成任务的大量代码,也就是说,如果我提供 x 我期望 y,但实现细节不是担心。 @shaunhusain ,所以根据这个anwser,不在范围内的命名函数不能用茉莉花测试? 是的,相信就是这样。如果您的大部分逻辑都在工厂或服务对象中,那么最好的 IMO 但同样适用,因为运行的测试只能访问对象的公共属性或方法。

以上是关于我们如何测试非范围角度控制器方法?的主要内容,如果未能解决你的问题,请参考以下文章

超时如何在 karma 中运行的角度测试中工作

在角度指令的控制器中测试 $emit

MockMVC 将测试控制器与会话范围 bean 集成

如何在 Spock 控制器测试中模拟 Grails 请求对象方法

如何从 chrome 控制台以角度访问 $scope 变量

角度传递范围到 ng-include