der*_*ata 4 javascript jasmine angularjs ionic-framework
我有一个返回promise的AngularJS服务.
尽管代码运行得很好,但测试给我带来了一些困难,因为承诺的"then"方法在我的单元测试中从未调用过.
常见的答案似乎是$rootScope.$apply()在" JasmineJS测试中未触发的AngularJS Promise Callback "一文中提到的调用.但是,如果我这样做,我的测试会尝试加载templates/home.html,这是不期望的:
PhantomJS 1.9.7 (Linux) Controller: ScanCtrl should invoke the barcode scanner when it is available FAILED
Error: Unexpected request: GET templates/home.html
No more request expected
Run Code Online (Sandbox Code Playgroud)
如果我没有包含$rootScope.$apply(),那么promise的"then"方法永远不会被调用,并且我得到一个错误,我的间谍没有被按预期调用:
PhantomJS 1.9.7 (Linux) Controller: ScanCtrl should invoke the barcode scanner when it is available FAILED
Expected spy go to have been called with [ 'enterQuantity', { barcodeId : '888888888888' } ] but it was never called.
Run Code Online (Sandbox Code Playgroud)
所以我的问题是 - 如何让这些测试工作?有什么方法可以避免打电话$rootScope.$apply()吗?或者,我是否需要找到一种让我的代码templates/home.html在$rootScope.$apply()调用时不会尝试的方法?
服务
.factory('BarcodeScannerService', ['$q', function ($q) {
return {
scanBarcode: function () {
var deferred = $q.defer();
plugins.barcodeScanner.scan(
function (result) {
console.log("We got a barcode\n" +
"Result: " + result.text + "\n" +
"Format: " + result.format + "\n" +
"Cancelled: " + result.cancelled);
deferred.resolve({"error": false, "barcode": result.text});
},
function (error) {
deferred.resolve({"error": true});
});
return deferred.promise;
}
};
}]
)
Run Code Online (Sandbox Code Playgroud)
单元测试
it('should invoke the barcode scanner when it is available', function () {
inject(function ($controller, $rootScope, $q) {
scope = $rootScope.$new();
$rootScopeHolder = $rootScope;
var deferred = $q.defer();
barcodeScannerServiceMock.scanBarcode = jasmine.createSpy('scanBarcode').andReturn(deferred.promise);
deferred.resolve({"error": false, "barcode": fakeBarcode2});
barcodeScannerServiceMock.isAvailable = jasmine.createSpy('isAvailable').andReturn(true);
//$scope, $timeout, Items, $state, SubmitCartService, $window
ScanCtrl = $controller('ScanCtrl', {
$scope: scope,
$window: windowMock,
Items: itemMock,
BarcodeScannerService: barcodeScannerServiceMock,
$state: stateMock
});
});
expect(barcodeScannerServiceMock.isAvailable).toHaveBeenCalled();
expect(barcodeScannerServiceMock.scanBarcode).toHaveBeenCalled();
//$rootScopeHolder.$apply();
expect(stateMock.go).toHaveBeenCalledWith('enterQuantity', { barcodeId: fakeBarcode2 });
});
Run Code Online (Sandbox Code Playgroud)
被测控制器
.controller('ScanCtrl', function ($scope, $timeout, $ionicModal, $state, BarcodeScannerService, $window) {
$scope.handleBarcodeScanError = function () {
var r = $window.confirm("Scanning failed. Try again?");
if (r === true) {
$state.go('scan');
}
else {
$state.go('home');
}
};
console.log("Scanner Avaialble?" + BarcodeScannerService.isAvailable());
if (BarcodeScannerService.isAvailable() === true) {
var barcodeResult = {};
BarcodeScannerService.scanBarcode()
.then(function(result){
barcodeResult = result;
if (barcodeResult.error === false) {
$state.go('enterQuantity', {barcodeId: barcodeResult.barcode});
}
else {
$scope.handleBarcodeScanError();
}
}, function(error){
$scope.handleBarcodeScanError();
});
}
//else, if barcode scanner is not available ask them to key it in
else {
var tempBarcode = $window.prompt('Enter barcode:');
$state.go('enterQuantity', {barcodeId: tempBarcode});
}
}
)
Run Code Online (Sandbox Code Playgroud)
完整代码: https ://github.com/derekdata/barcode-cart-builder/
控制器:www/js/app.js
服务:www/js/services/services.js
测试:www_test/spec/controllers/ScanCtrlTest.js
提前感谢你能给我的任何见解.
您似乎误解了该解决方案.你需要调用$ rootScope.$ digest()而不是$ rootScope.$ apply(); $ digest循环是导致promises检查是否满足的原因.此外,您只需要为当前作用域调用$ digest()循环,因此您的实际调用将是作用域.$ digest(),并置于断言之上.
| 归档时间: |
|
| 查看次数: |
3212 次 |
| 最近记录: |