【问题标题】:How to test John papa vm.model unit testing with jasmine?如何用茉莉花测试 John papa vm.model 单元测试?
【发布时间】:2015-04-11 23:10:18
【问题描述】:

我使用 John papa 角度样式指南,我的控制器看起来像:

跟风John papa style controller style guide:

function testController() {

    var vm = this;

    vm.model = { name: "controllerAs vm test" };
}

我的测试代码如下:

describe('Controller: testController', function () {

    beforeEach(module('myApp'));

    var testController;

    beforeEach(inject(function ($controller) {
        scope = {};

        testController = $controller('testController', {
        });

    }));

    it('should have vm.model defined and testController.vm.model is equal to controllerAs vm test', function () { 
        expect(testController.vm).toBeDefined();  
        expect(testController.vm.model).toBeDefined();     
        expect(testController.vm.model.name).toEqual("controllerAs vm test");
    });
});

结果:

测试失败: 结果消息:预期未定义。 在堆栈中

所以我的问题是我们如何测试 vm.model 和其他变量?我在指南中没有找到合适的指南:controllers

【问题讨论】:

    标签: angularjs unit-testing angularjs-scope jasmine karma-jasmine


    【解决方案1】:

    vm 通过vm = this; 等于实例本身

    因此,所有属性都直接挂在对象上。

    function foo(){
      var vm = this;
    
      vm.name = 'Josh';
    }
    
    var myFoo = new foo();
    myFoo.name; // 'Josh';
    

    因此,您需要做的就是改变您的期望以删除 vm 属性。

    expect(testController).toBeDefined();  
    expect(testController.model).toBeDefined();     
    expect(testController.model.name).toEqual("controllerAs vm test");
    

    为了证明这一点,这是您的确切示例以及相关的 Jasmine 测试。

    function testController() {
    
      var vm = this;
    
      vm.model = {
        name: "controllerAs vm test"
      };
    }
    
    
    angular.module('myApp', [])
      .controller('testController', testController);
    
    describe('Controller: testController', function() {
    
      beforeEach(module('myApp'));
    
      var testController;
    
      beforeEach(inject(function($controller) {
        scope = {};
    
        testController = $controller('testController', {});
    
      }));
    
      it('should have model defined and testController.model.name is equal to controllerAs vm test', function() {
        expect(testController).toBeDefined();
        expect(testController.model).toBeDefined();
        expect(testController.model.name).toEqual("controllerAs vm test");
      });
    
      it('should not have a property called vm', function() {
        expect(testController.vm).toBeUndefined();
      });
    });
    <link href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine-html.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/boot.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.4/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.4/angular-mocks.js"></script>

    【讨论】:

    • 作为一个函数,你的答案看起来不错,但这里我的问题是当我通过以下方式初始化控制器实例时: testController = $controller('testController', { });那么 testController.vm 应该可以工作但不能工作。所以我的问题是那些使用 angular john papa 的控制器作为 vm 语法并使用 jasmine 进行测试的人。
    • @UtpalKumarDas - 在后台$controller 只是调用new(),所以它的工作方式相同。
    • @UtpalKumarDas - 我使用 Angular 已经有好几年了,并且对 Jasmine 进行了大量测试。我试图解释这不是 Angular 的东西,而是 JavaScript 的东西。 vm 不是控制器上的属性...它是一个被函数范围封闭的变量。因此,以这种方式使用时,它将永远存在于您的控制器上。 $controller 不会改变 JS 的工作方式。
    • 是的,现在我理解了 vm=testControllerInstance,所以在 testControllerInstance 中可以找到 vm.variables。非常感谢您的回答。太好了!!
    • 乔希提供的答案确实有效,但我发现没有必要包括:scope = {}; Here 是我在 Codepen 上创建的示例。
    【解决方案2】:

    testController vm,因为您在控制器中设置了var vm = this。因此,为了使您的测试代码与您的控制器代码更相似,您也可以尝试在测试中将您的控制器设置为 vm 而不是 testController

    describe('Controller: testController', function () {
        // we work with "vm" instead of "testController" to have consistent verbiage
        // in test and controller
        var vm;
    
        beforeEach(module('app'));
        beforeEach(inject(function ($controller) {
            vm = $controller('testController', {}, {});
        }));
    
        it('should have vm.model defined and testController.vm.model is equal to controllerAs vm test', function () {
    
            // vm=this in controller
            expect(vm)
                .toBeDefined();
    
            // Testing primitives
            expect(vm.foo)
                .toBeDefined();
            expect(vm.foo)
                .toEqual('bar');
    
            // Testing objects
            expect(vm.model)
                .toBeDefined();
            expect(vm.model.name)
                .toEqual("Batman");
    
            // Testing a method
            expect(vm.greet())
                .toBeDefined();
            expect(vm.greet())
                .toEqual('Hello There');
        });
    });
    

    控制器代码

    (function () {
        'use strict';
    
        angular
            .module('app')
            .controller('testController', testController);
    
        /* @ngInject */
        function testController() {
            var vm = this;
    
            // Primitives
            vm.foo = 'bar';
    
            // Objects
            vm.model = {
                name: 'Batman'
            };
    
            // Methods
            vm.greet = function () {
                return 'Hello There';
            };
        }
    })();
    

    希望这会有所帮助。祝你好运。

    【讨论】:

      【解决方案3】:

      我将创建一个新模块并将其作为依赖项注入到 app 模块中,以使其简单且可测试。使用 John Papa 的样式指南测试控制器:

      (function () {
        'use strict';
      
        angular
          .module('test')
          .controller('testController', testController);
      
        function testController() {
          var vm = this;
          vm.model = { name: "controllerAs vm test" };
        }
      })();
      

      规范现在看起来像这样:

      'use strict';
      
      describe('testController', function() {
        var testController;
        beforeEach(module('test'));
      
        beforeEach(function () {
          inject(function($injector) {
            testController = $injector.get('$controller')('testController', {});
          });
        });
      
        it('should have model defined and testController.name is equal to controllerAs vm test', function() {
          expect(testController).toBeDefined();
          expect(testController.name).toEqual("controllerAs vm test");
        });
      });
      

      希望这对寻找类似解决方案的人有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-27
        • 1970-01-01
        • 2022-01-23
        • 2020-11-25
        • 2020-08-19
        • 2015-10-01
        • 2016-06-14
        相关资源
        最近更新 更多