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