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

模拟要在不同测试中重用的angularjs值,angularjs,unit-testing,jasmine,karma-jasmine,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 Aut


我有一个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中用户名的返回值。它总是返回我在beforeach中设置的模拟值

1) 我是不是遗漏了什么


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

首先,您试图监视字符串类型的字段(
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());
            });
        });
    });
})();

借助@JD Nizet的回答,我已经解决了这个问题。把它贴在这里,因为它可能是任何遇到同样问题的人的一个学习点

首先,@JD Nizet提供的解决方案不起作用,原因是我的服务设计不好

我应该将完整的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 _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;
    }
  }
})();
var\u 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;
    }
  }
})();

谢谢你的意见。但问题似乎没有解决。我试着用你的方法。但是第二个测试“应该是真的,用户名有值”失败。becos authStore.username为null,即使我将其设置为“test”,但您的代码设计糟糕,测试表明:既然用户名已经在authStore中,那么将其存储在AuthService的另一个变量中有什么意义?或者,换一种方式说,拥有一个独立的authStore服务有什么意义,因为AuthService完全能够在没有帮助的情况下存储用户名?让两个独立的服务来存储同一个东西不是一个好主意。AuthService在实例化authStore时从authStore读取用户名,之后再也不会读取它。但是您的测试更改了authSTore.username,并假设AuthService应该看到更改。我同意我的服务设计不好。我已经创建了一个单独的authStore becos,我需要在服务之间共享用户名。我不想让他们依赖于完整的authService。只是为了检索用户名。我的想法有缺陷。谢谢你的意见。如果有人能让我知道我最初的方法失败的原因。这将是一个gr8帮助。提前谢谢