【问题标题】:unit test template in angular modal service ($uibModal)角度模态服务中的单元测试模板 ($uibModal)
【发布时间】:2017-02-24 23:11:08
【问题描述】:

我有一个非常简单的 service.show(),它基本上通过一些配置调用 $uibModal 并返回模态实例

function modalService($uibModal) {
  return {
    show(message) {
      return $uibModal.open({
        bindToController: true,
        controllerAs: '$ctrl',
        template: "<div id='message'>{{$ctrl.message}}</div>",
        controller: [function() {
          this.message = message;
        }]
      });
    }
  }
}

我想编写一个测试来验证实际的模态以及它是否包含预期的消息。像这样的:

it('should show correct message', (done) => {
    modal = modalService.show('hello');
    modal.rendered.then(()=> {
      expect($('#message').text()).toBe('hello');
      done()
    });
  });

但是rendered 承诺永远不会得到解决。我可以做一些解决方法,比如将expect 包装成$timeout 并做$timeout.flush() 但不确定这是否是正确的方式,即使这样我仍然无法进行清理(afterEach)来关闭模式和准备好测试另一条消息。

【问题讨论】:

    标签: angularjs unit-testing jasmine modal-dialog karma-jasmine


    【解决方案1】:

    正确的方法是打开模式窗口查找消息并关闭它,因为引导程序使用ngAnimate 制作动画,我们必须包含ngAnimateMock 模块来刷新待处理的动画。

    查看以下代码以获取解决方案:

    var myApp = angular.module('myApp', ['ngAnimate', 'ui.bootstrap']);
    
    myApp.factory('modalService', ['$uibModal', function($uibModal) {
      return {
        show(message) {
          return $uibModal.open({
            bindToController: true,
            controllerAs: '$ctrl',
            template: '<div id="message">{{$ctrl.message}}</div>',
            controller: [function() {
              this.message = message;
            }]
          });
        }
      }
    }]);
    
    describe('modalService service', function() {
      describe('modalService', function() {
        var modalService;
        var $rootScope;
        var $animate;
    
        beforeEach(function() {
          module('ngAnimateMock')
          module('uib/template/modal/window.html')
          module('myApp');
        });
    
        beforeEach(inject(function(_$rootScope_, _modalService_, _$animate_) {
          $rootScope = _$rootScope_;
          modalService = _modalService_;
          $animate = _$animate_;
        }));
    
        it('should open the dialog with the correct message', () => {
          var modal = modalService.show('hello');
    
          $rootScope.$digest();
          // Finish the animation.
          $animate.flush();
    
          expect($('#message').text()).toEqual('hello');
    
          // Close the dialog.
          modal.close();
    
          $rootScope.$digest();
          // Finish the animation.
          $animate.flush();
        });
    
        it('again should show the correct message', () => {
          var modal = modalService.show('new message');
    
          $rootScope.$digest();
          // Finish the animation.
          $animate.flush();
    
          expect($('#message').text()).toEqual('new message');
    
          // Close the dialog.
          modal.close();
    
          $rootScope.$digest();
          // Finish the animation.
          $animate.flush();
        });
      });
    });
    <body>
      <!-- because we are testing our controller and not running we don't need a controller or even a module -->
      <!-- so there is no ng-app or ng-controller in the markup -->
    
      <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine.css">
    
      <!-- the order that these files load is critical, think twice before changing -->
      <script src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine.js"></script>
      <script src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine-html.js"></script>
      <script src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/boot.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
      <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-mocks.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap-tpls.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap.min.js"></script>
    
      <h2>Finished jasmine-unit-test</h2>
    
    </body>

    【讨论】:

    • 第一个测试通过,但第二个测试失败并显示消息 Expected 'new messagehello' to equal 'new message'. modal.close() 不会从 dom 中删除模态。你知道为什么会发生吗?
    • 为什么我需要 module('uib/template/modal/window.html') ?
    • 我提供的代码 sn-p,两个测试都通过了。你能提供codepen/jsfiddle等,这样我就可以调查一下。关于您的其他问题,您需要包含module('uib/template/modal/window.html'),因为当您在内部进行$uibModal.open() 调用时,它会获取模板'window.html'。
    • 这是更新的小提琴; jsfiddle.net/gauravmahto/dj3fbztu/3 在这个小提琴中,我没有禁用动画,而是手动刷新动画,因为我认为在内部它正在做一些额外的工作,并且要了解我必须更深入地挖掘。但这里的主要问题是,如果您在第 44 行更改断言以使其失败,您将看到测试实际上失败了,并且确认调用 modal.rendered 返回的承诺确实已解决,因此调用了链式函数.
    • 这可能无关紧要,但无论如何这里有一个关于引导测试技巧sitepoint.com/… 的有趣话题。另一个STOF回答stackoverflow.com/questions/33405666/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-24
    • 1970-01-01
    • 2018-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多