执行依赖AWS cognito的angularjs服务的单元测试时出错

Error while executing Unit testing of angularjs service that depends on AWS cognito

本文关键字:单元测试 出错 服务 angularjs AWS cognito 执行 依赖      更新时间:2023-09-26

我是angularjs单元测试的新手。我使用Jasmine, karma进行单元测试。

我已经写了一个angularjs服务来管理我对AWS的请求和响应。它公开了login, register等api,这些api会在内部使用aws cognito sdk。

当我构建应用程序并将其部署到本地时,此服务工作正常。

当我试图为这个服务编写一些单元测试并运行时,它失败了,出现以下错误

TypeError: undefined不是一个对象(求值'r.CognitoIdentityServiceProvider')在app/第三方/amazon-cognito-identity.min.js: 19

我假设我在测试框架中做错了什么。

这是我的angular服务(aws.service.js)

(function(){
    'use strict';
    angular
        .module('portal')
        .factory('AWSService',AWSService);
    AWSService.$inject = ['$rootScope'];
    function AWSService($rootScope){
        var service = {};
        service.Login = Login;
        service.SignOut = SignOut;
        service.IsSessionValid = IsSessionValid;
        service.Register = Register;
        service.ConfirmReg = ConfirmReg;
        service.GetUserDetails = GetUserDetails;
        initService();
        return service;

        function initService(){
            // Cognito Identity Pool Id
            AWS.config.region = 'XXXXXXX'; // Region
            AWS.config.credentials = new AWS.CognitoIdentityCredentials({
                IdentityPoolId: 'XXXXXXXXX'
            });
            // Cognito User Pool Id
            AWSCognito.config.region = 'XXXXXXXX';
            AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
                                                    IdentityPoolId: 'XXXXXXXX'
                                                    });
        }
        function getUserPool(){
            var poolData = { UserPoolId : 'XXXXXXX',
                ClientId : 'XXXXXXXXXXXX'
            };

            var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
            return userPool;
        }
        function Login(authDetails, callback) {
            console.log('In AWS service login');
             if (authDetails == null || authDetails.UserName == null || authDetails.Password == null) {
                  throw new Error('Username and password information are required.');
             }
             try{
                var authenticationData = {
                                             Username : authDetails.UserName,
                                             Password : authDetails.Password,
                                        };
                var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider
                                                        .AuthenticationDetails(authenticationData);
                var userData = {
                                    Username : authDetails.UserName,
                                    Pool : getUserPool()
                                };
                var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
                cognitoUser.authenticateUser(authenticationDetails, callback);
            } catch(e){
                alert(e.name+" "+e.message)
            }

        }
        function IsSessionValid(callback) {
            var cognitoUser = getUserPool().getCurrentUser();
            if (cognitoUser != null) {
                cognitoUser.getSession(function(err, session) {
                    if (err) {
                        alert(err);
                        callback({ success: false, message: 'Session is invalid'});
                    }
                    console.log('session validity: ' + session.isValid());
                    callback({ success: true, message: 'Session is valid'});
                });
            }
        }
        function SignOut(){
            var cognitoUser = getUserPool().getCurrentUser();
            if (cognitoUser != null) {
                console.log('session is valid, signing out');
                cognitoUser.signOut();
            }else {
                console.log('session already expired');
            }
        }
        function Register(userInfo, callback){
            var attributeList = [];
            var dataEmail = {
                Name : 'email',
                Value : userInfo.email
            };
            var dataFirstName = {
                Name : 'given_name',
                Value : userInfo.firstName
            };
            var dataLastName = {
                Name : 'family_name',
                Value : userInfo.lastName
            };
            var attributeEmail = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataEmail);
            var attributeFirstName = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataFirstName);
            var attributeLastName = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataLastName);
            attributeList.push(attributeEmail);
            attributeList.push(attributeFirstName);
            attributeList.push(attributeLastName);

            getUserPool().signUp(userInfo.email, userInfo.password, attributeList, null, callback);
        }
        function GetUserDetails(callback){
            IsSessionValid(function (response) {
                if (response.success) {
                    var cognitoUser = getUserPool().getCurrentUser();           
                    cognitoUser.getUserAttributes(function(err, result) {
                        if (err) {
                            alert(err);
                            return;
                        }
                        for (i = 0; i < result.length; i++) {
                            console.log('attribute ' + result[i].getName() + ' has value ' + result[i].getValue());
                        }
                    })
                }
                else{
                    console.log('invalid session');
                }
            })

        }
        function ConfirmReg(confirmCode, callback){
        }

    }

})();

这是我的单元测试代码(aws.services.test.js)

'use strict'
describe('AWSService', function(){
    var AWSService, myRootscope;
    console.log('In service describe');
    beforeEach(angular.mock.module("portal"))
    it("Should have created AWS service", inject(function($rootScope, _AWSService_){
        console.log('Service injection start');
        AWSService = _AWSService_;
        myRootscope = $rootScope;
        console.log('Service injection done');
    }));
    it('Test AWS service - login', function(){
        try{
            console.log('Calling login function');
            AWSService.Login(null, null);
        }catch(e){
            console.log(e);
            expect(e.message).toEqual('Username and password information are required.');
        }
    });
});

My Karma config

module.exports = function(config) {
  'use strict';
  config.set({
    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,
    // base path, that will be used to resolve files and exclude
    basePath: '../',
    // testing framework to use (jasmine/mocha/qunit/...)
    // as well as any additional frameworks (requirejs/chai/sinon/...)
    frameworks: [
      'jasmine',
      'browserify'
    ],

    // list of files / patterns to load in the browser
    files: [
      // bower:js
      'bower_components/jquery/dist/jquery.js',
      'bower_components/angular/angular.js',
      'bower_components/bootstrap/dist/js/bootstrap.js',
      'bower_components/angular-animate/angular-animate.js',
      'bower_components/angular-cookies/angular-cookies.js',
      'bower_components/angular-resource/angular-resource.js',
      'bower_components/angular-route/angular-route.js',
      'bower_components/angular-sanitize/angular-sanitize.js',
      'bower_components/angular-touch/angular-touch.js',
      'bower_components/aws-sdk-js/dist/aws-sdk.js',
      'bower_components/moment/moment.js',
      'bower_components/sjcl/sjcl.js',
      'bower_components/jsbn/jsbn.js',
      'bower_components/angular-mocks/angular-mocks.js',
      // endbower
      'app/*.js',
      'app/app-services/*.js',
      'app/**/*.js',
      'test/mock/**/*.js',
      'test/spec/**/*.js'
    ],
    // Browserify config
    browserify: {
          watch: true,
          debug: true
    },
    preprocessors: {
        'app/*.js' : ['browserify'],
        'test/spec/services/aws.services.test.js': [ 'browserify' ]
     },
    // list of files / patterns to exclude
    exclude: ['karma.conf.js', 'protractor-conf.js'],

    // web server port
    port: 8080,
    // Start these browsers, currently available:
    // - Chrome
    // - ChromeCanary
    // - Firefox
    // - Opera
    // - Safari (only Mac)
    // - PhantomJS
    // - IE (only Windows)
    browsers: [
      'PhantomJS'
    ],
    // Which plugins to enable
    plugins: [
      'karma-phantomjs-launcher',
      'karma-jasmine',
      'karma-chrome-launcher',
      'karma-browserify',
    ],
    // Continuous Integration mode
    // if true, it capture browsers, run tests and exit
    singleRun: false,
    colors: true,
    // level of logging
    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
    logLevel: config.LOG_DEBUG,
    // Uncomment the following lines if you are using grunt's server to run the tests
    // proxies: {
    //   '/': 'http://localhost:9000/'
    // },
    // URL root prevent conflicts with the site root
    // urlRoot: '_karma_'
  });
};

我知道我必须模拟aws-sdk以确保我的服务单独经过单元测试。但是在去那里之前,我看到karma甚至在加载我的模块之前就失败了。

我正在使用以下命令 运行我的测试
 karma start karma.conf.js --browsers=Chrome --single-run=false

我在控制台

中得到以下错误
Chrome 53.0.2785 (Windows 10 0.0.0) ERROR
  Uncaught TypeError: Cannot read property 'CognitoIdentityServiceProvider' of undefined
  at app/third-party/amazon-cognito-identity.min.js:19

我怀疑如果我的AWS SDK和它的依赖不能正确加载。如果你在我的代码中看到任何问题,请告诉我。

您应该将与cognito相关的文件(amazon-cognito-identity和aws cognito sdk)放在Karma的files字段中。