模拟要在不同测试中重用的angularjs值

时间:2016-01-16 17:24:36

标签: angularjs unit-testing jasmine karma-jasmine


我有一个angularjs服务,它使用角度值来存储用户名。

(function() {
  'use strict';

  angular.module('myapp.services', [])
    .service('authService', AuthService)
    .value('authStore', {
      username: null
    });

  AuthService.$inject = ['authStore'];

  function AuthService(authStore) {
    var svc = this;
    var _username = authStore.username;
    svc.isLoggedIn = IsLoggedIn;
    svc.logout = Logout;
    svc.login = Login;
    svc.getUsername = GetUsername;

    function IsLoggedIn() {
      return _username != null && _username && _username != '';
    }

    function Logout() {
      authStore.username = null;
      _username = null;
    }

    function GetUsername() {
      return _username;
    }

    function Login(username) {
      authStore.username = username;
      _username = username;
    }
  }
})();

我正在使用jasmine来测试我的isLoggedin方法。 所以我的测试会是;

(function () {
    'use strict'
    describe('Auth Service Tests', function () {
        beforeEach(module('ionic'));
        beforeEach(module('myapp.services'));
        var provider
        var authStore;
        var authService;

        beforeEach(function () {
            module(function ($provide) {
                authStore = {
                    username: null
                };
                $provide.value('authStore', authStore);
            });
        });

        beforeEach(inject(function (_authService_) {
            authService = _authService_;
        }));

        describe('isLoggedIn', function () {
            it('should be false the username is null.', function () {
                spyOn(authStore, 'username').and.returnValue(null);
                expect(authService.isLoggedIn()).toBe(false); //success
                //(this is because the authStore is initialized with username: null, not because of the spyOn line above)
                console.log(authService.getUsername()); //null
            });

            it('should be true the username has a value', function () {
                spyOn(authStore, 'username').and.returnValue('test');
                expect(authService.isLoggedIn()).toBe(true);  //Failed
                console.log(authService.getUsername()); //null
            });
        });
    });
})();

我遇到的问题是。我无法在authStore中更改用户名的返回值。它总是返回我在beforeEach中设置的模拟值。

1)我在这里错过了什么吗?

2)什么是模拟在测试中使用的angularjs值的正确方法。在这样的场景中,需要将其从测试更改为测试???

2 个答案:

答案 0 :(得分:0)

首先,您正在尝试监视字符串类型(authStore.username)的字段。这是不可能的。字符串不是函数。它无法返回任何东西。只有一个价值。间谍用于替换另一个伪造的功能。不要改变字符串的值。

但这无论如何都是必要的:因为它只是一个字符串,所以没有什么可以窥探的。只需设置您希望拥有的值即可。您甚至不需要提供虚假的实现,因为虚假实现与真实实现相同:

(function () {
    'use strict'
    describe('Auth Service Tests', function () {
        beforeEach(module('ionic', 'myapp.services'));

        var authStore;
        var authService;

        beforeEach(inject(function (_authService_, _authStore_) {
            authService = _authService_;
            authStore = _authStore_;
        }));

        describe('isLoggedIn', function () {
            it('should be false the username is null.', function () {
                authStore.username = null;

                expect(authService.isLoggedIn()).toBe(false);
                console.log(authService.getUsername());
            });

            it('should be true the username has a value', function () {
                authStore.username = 'test';

                expect(authService.isLoggedIn()).toBe(true);
                console.log(authService.getUsername());
            });
        });
    });
})();

答案 1 :(得分:0)

我在@JD Nizet的回答的帮助下解决了这个问题。在这里发布,因为对于遇到同样问题的人来说,这可能是一个学习点。

第一关,@JD Nizet提供的解决方案无效,原因是我的服务设计不佳。

我应该将完整的authStore存储为服务中的私有变量而不仅仅是用户名。

  

var _username = authStore.username;

应该改为

  

var _authStore = authStore;

然后我必须更新我的方法以使用新的_authStore并且测试工作! 这是改变的完整服务;

(function() {
  'use strict';

  angular.module('myapp.services', [])
    .service('authService', AuthService)
    .value('authStore', {
      username: null
    });

  AuthService.$inject = ['authStore'];

  function AuthService(authStore) {
    var svc = this;
    var _authStore = authStore;
    svc.isLoggedIn = IsLoggedIn;
    svc.logout = Logout;
    svc.login = Login;
    svc.getUsername = GetUsername;

    function IsLoggedIn() {
      return _authStore.username != null && _authStore.username && _authStore.username != '';
    }

    function Logout() {
      _authStore.username = null;
    }

    function GetUsername() {
      return _authStore.username;
    }

    function Login(username) {
      _authStore.username = username;
    }
  }
})();