Karma-Jasmine: 如何正确地对模态框进行间谍测试?

IT小君   2023-05-12T08:27:55
情况: 我正在对我的Angular/Ionic应用进行单元测试。 我在modal方面遇到了困难。目前,我可以测试modal是否已被调用。到目前为止,我无法测试modal的proper show()和hide()方法。 我得到了以下错误: TypeError: $scope.modal_login.show不是一个函数 错误:show()方法不存在 TypeError: $scope.modal_login.hide不是一个函数 错误:hide()方法不存在 我认为这完全取决于间谍。我不知道如何正确地监视modal,我认为一旦完成,一切都会很好。 代码: 控制器: 注意:open_login_modal函数的代码已经重构以便于测试。原始代码如下: 测试: App测试 describe('App tests', function() { beforeEach(module('my_app.controllers')); function fakeTemplate() { 返回{ 那么: function(modal){ $scope.modal_login = modal; } } } beforeEach(inject(function(_$controller_, _$rootScope_) { $controller = _$controller_; $rootScope = _$rootScope_; $scope = _$rootScope_.$new(); $ionicModal = { fromTemplateUrl: jasmine.createSpy('$ionicModal.fromTemplateUrl').and.callFake(fakeTemplate) }; var controller = $controller('MainCtrl', { $scope: $scope, $rootScope: $rootScope, $ionicModal: $ionicModal }); })); describe('Modal tests', function() { beforeEach(function() { $scope.open_login_modal(); spyOn($scope.modal_login, 'show'); // NOT WORKING spyOn($scope.modal_login, 'hide'); // NOT WORKING }); it('should open login modal', function() { expect($ionicModal.fromTemplateUrl).toHaveBeenCalled(); // OK expect($ionicModal.fromTemplateUrl.calls.count()).toBe(1); // OK expect($scope.modal_login.show()).toHaveBeenCalled(); // NOT PASS expect($scope.for_test_only).toEqual(true); // NOT PASS }); it('should close login modal', function() { $scope.close_login_modal(); expect($scope.modal_login.hide()).toHaveBeenCalled(); // NOT PASS }); }); }); 你可以从代码中看到,$scope.for_test_only应该等于true,但是没有被识别。相反,我得到了以下错误消息: 预期未定义等于true。 show()和hide()方法也是如此。它们没有被测试看到。 我认为这是因为它们没有在spy中声明。 问题: 如何正确地监视modal? 非常感谢!
点击广告,支持我们为你提供更好的服务
评论(1)
IT小君

这里的问题可以推广到如何正确地监听一个Promise。你所做的很对。

然而,如果你想要测试无论你的Promise成功的回调是如何被调用的,你需要执行两个步骤:

  1. 模拟服务(在你的情况下是$ionicModal)并返回一些虚假的函数
  2. 在那个虚假函数中,执行生产代码传递给你的回调函数。

这里是一个例子:

//创建服务的模拟(步骤1)
var $ionicModal = jasmine.createSpyObj('$ionicModal', ['fromTemplateUrl']);

//创建一个例子响应,它只调用你的回调函数(步骤2)
var successCallback = {
   then: function(callback){
       callback.apply(arguments);
   }
};

$ionicModal.fromTemplateUrl.and.returnValue(successCallback);

当然,如果你不想自己维护Promise,你也可以始终使用$q:

//在你的beforeeach中
var $ionicModal = jasmine.createSpyObj('$ionicModal', ['fromTemplateUrl']);
//创建一个你将要传递和解析的模拟modal
var modalMock = jasmine.createSpyObj('modal', ['show', 'hide']);
$ionicModal.fromTemplateUrl.and.callFake(function(){
    return $q.when(modalMock);
});


//在你的测试中
//调用scope $digest来触发angular的digest/apply生命周期
$scope.$digest();
//期望一些事情发生
expect(modalMock.show).toHaveBeenCalled();
2023-05-12T08:28:20   回复