在angularjs测试中模拟服务依赖性

时间:2015-06-17 11:29:53

标签: angularjs unit-testing jasmine

我有一个服务CurrentUser,它依赖于StorageFactory。在此服务的构造函数中,如果StorageFactory.get返回用户,我将用户设置为该用户,否则设置默认用户值。现在,我想测试一下。

我已成功完成这项工作,但我对我使用的方法不满意。我得到了这种方法的灵感here

我已粘贴以下代码。如果您愿意,我还创建了一个要点here。我删除了代码中不相关的部分以避免分心。这是使用ES6类和模块编写的,但这不应对测试产生任何影响。

该方法的问题是模拟将用于所有测试,这可能不是一件坏事,但我想控制它。有没有办法让这个模拟只对这个测试产生影响? 找到更好方法的一个障碍是必须在angular创建模拟CurrentUserModule模块之前完成模拟。有没有更好的测试方法?对此我有任何建议。

服务

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<div id="msg"> ERROR MESSAGE OR SUCCESS </div>

<div id="msg2"> ERROR2 MESSAGE OR SUCCESS </div>

测试

import StorageFactoryModule from 'app/common/services/StorageFactory';

class CurrentUser {
    constructor(StorageFactory) {

    this.storageKey = 'appUser';

    this.StorageFactory = StorageFactory;

    this.profile = initializeUser.call(this);

    function initializeUser() {
        var userFromStorage = StorageFactory.get(this.storageKey);
        if (userFromStorage != null) {
            return userFromStorage;
        } else {
            // return default user
        }
    }

}
// more methods, that are removed for brevity

}

CurrentUser.$inject = ['StorageFactory'];

export default angular.module('CurrentUserModule', [StorageFactoryModule.name])
    .service('CurrentUser', CurrentUser);

1 个答案:

答案 0 :(得分:1)

我设法找到了一种更好的方法,如下所示。我最初是以错误的方式做事(现在觉得很愚蠢)。我没有创建一个模拟模块,而是创建了一个覆盖原始模块的真实模块,这就是它影响所有测试的原因。现在,我正在创建一个模拟模块并使用$ provide来覆盖StorageFactory,这将仅影响当前套件。

beforeEach(function () {
    angular.mock.module('StorageFactoryModule');
    module(function($provide) {
        $provide.value('StorageFactory', storageFactoryMock); 
    });
    angular.mock.module('CurrentUserModule');
});

编辑:通过创建一个接受用户作为参数的函数并根据传递的用户创建模块,重构我的代码并使其更灵活。

var correctUser = {userid: 'abc', token: 'token'};
var defaultUser = {userid: '', token: ''};

function createStorageFactoryMock(userInStorage) {
        return {
            get: function () {
                return userInStorage;
            },
            put: function (key, newUser) {
                userInStorage = newUser;
            },
            remove: function () {
                userInStorage = undefined;
            }
        }
    }

function CreateUserModule(user = correctUser) {
        angular.mock.module('StorageFactoryModule');
        module(function ($provide) {
            $provide.value('StorageFactory', createStorageFactoryMock(user));
        });
        angular.mock.module('CurrentUserModule');
    }

现在在我的测试中,我可以针对不同的场景模拟不同的模块,并相应地编写我的测试。欢迎任何反馈。

it('should Initialize User from storageFactory if already exists in storage', function () {
    CreateUserModule();
    inject(function (CurrentUser) {
        expect(CurrentUser.profile).toEqual(correctUser);
    });
});

it('should Initialize default user if user not present in storage', function () {
    CreateUserModule(null);
    inject(function (CurrentUser) {
        expect(CurrentUser.profile).toEqual(defaultUser);
    });
});