javascript – 在Angular应用程序中使用Jasmine测试SignalR的问题

我这里有一个严肃的问题.我的应用程序依赖于SignalR功能,但由于这一点,我无法编写单元测试.我是测试框架的新手,仅在简单的情况下使用Jasmine.事实证明SignalR对我来说是一个太大的挑战,但我需要了解如何成功测试它.
这是我的CommsApp.ts文件[typescript]:

/// <reference path="References.ts" />
var commsAnimationsModule = angular.module('forge.communications.animations', ['ngAnimate']);
var commsDirectivesModule = angular.module('forge.communications.directives', []);
var commsServicesModule = angular.module('forge.communications.services', []);
var commsFiltersModule = angular.module('forge.communications.filters', []);

var commsApp = angular.module('forge.communications.CommsApp',
    [
        'ngRoute',
        'ngAnimate',
        'cfValidation',
        'ui.bootstrap',
        'forge.communications.animations',
        'forge.communications.directives',
        'forge.communications.services',
        'forge.communications.filters',
        'angularFileUpload',
        'timeRelative'
    ]);

commsApp.config(function ($routeProvider: ng.route.IRouteProvider, $locationProvider: any) {

        $locationProvider.html5Mode(true);
        $routeProvider.
            when('/scheduled-messages', {
                templateUrl: '/forge/CommsApp/js/Controllers/ScheduledMessageList/ScheduledMessageList.html',
                controller: 'ScheduledMessageListController'
            }).
            when('/geotriggered-messages', {
                templateUrl: '/forge/CommsApp/js/Controllers/GeoMessageList/GeoMessageList.html',
                controller: 'GeoMessageListController'
            }).
            when('/scheduled-message/create', {
                templateUrl: '/forge/CommsApp/js/Controllers/CreateScheduledMessage/CreateScheduledMessage.html',
                controller: 'CreateScheduledMessageController'
            }).
            when('/scheduled-message/edit/:id', {
                templateUrl: '/forge/CommsApp/js/Controllers/EditScheduledMessage/EditScheduledMessage.html',
                controller: 'EditScheduledMessageController'
            }).
            when('/geotriggered-message/create', {
                templateUrl: '/forge/CommsApp/js/Controllers/CreateGeotriggeredMessage/CreateGeotriggeredMessage.html',
                controller: 'CreateGeotriggeredMessageController'
            }).
            when('/geotriggered-message/edit/:id', {
                templateUrl: '/forge/CommsApp/js/Controllers/EditGeotriggeredMessage/EditGeotriggeredMessage.html',
                controller: 'EditGeotriggeredMessageController'
            }).
            otherwise({
                redirectTo: '/scheduled-messages'
            });
    });

commsApp.run(function ($rootScope: ICommsRootScope, commsSignalrEventService: CommsSignalrEventService, commsMgmtHttpService: CommsMgmtHttpServiceClient) {

    // set up the items on the root scope
    $rootScope.SelectedLocale = 'en-ie';
    $rootScope.ForgeApplicationKey = "9496B737-7AE2-4FBD-B271-A64160759177";
    $rootScope.AppVersionString = "1.0.0";
    $rootScope.SessionToken = getCookie("ForgeSessionToken");

    commsSignalrEventService.initialize().done(() => {
        // send any messages about a new user logging in to the application here.
    });

    // call this at app startup to  pre-cache this data for the create and edit pages
    commsMgmtHttpService.GetUpdateMessageEditorOptions();
});

function getCookie(name:string) {
    var value = "; " + document.cookie;
    var parts = value.split("; " + name + "=");
    if (parts.length == 2) return parts.pop().split(";").shift();
}

这是测试文件(我删除了大部分代码,因为它无论如何都没有工作,我一直在追逐自己的尾巴):

describe('forge.communications.CommsApp', function () {

    beforeEach(module('forge.communications.CommsApp'));

    var route, rootScope, proxy, commsSignalrEventService;

    beforeEach(inject(function (_$route_, _$rootScope_, _commsSignalrEventService_) {
        route = _$route_,
        rootScope = _$rootScope_;
        commsSignalrEventService = _commsSignalrEventService_;
    }));

    describe("should map routes to controllers and templates", function () {

        it("/scheduled-messages route should be mapped to ScheduledMessageListController", function () {
            expect(2).toEqual(2);
            expect(route.routes['/scheduled-messages'].controller).toBe('ScheduledMessageListController');
        });

    });
});

这是CommsSignalREventService.ts文件:

var servicesModule: ng.IModule = angular.module('forge.communications.services');

servicesModule.factory('commsSignalrEventService', function ($rootScope): CommsSignalrEventService {
    return new CommsSignalrEventService($rootScope);
});

class CommsSignalrEventService {

private $rootScope: ng.IScope;
private proxy:any = null;

constructor($rootScope) {
    this.$rootScope = $rootScope;
}

public initialize(): JQueryPromise<any>{

    this.proxy = $.connection['communicationsCenterHub'];

    console.log('proxy',this.proxy);

    //scheduled messages
    this.proxy.client.broadcastScheduledMessageCreatedEvent = (messageId: number) => {
        this.$rootScope.$broadcast('comms-message-created', { messageId: messageId });
    };

    this.proxy.client.broadcastScheduledMessageUpdatedEvent = (messageId: number) => {
        this.$rootScope.$broadcast('comms-message-updated', { messageId: messageId });
    };

    this.proxy.client.broadcastScheduledMessageStateChangedEvent = (messageId: number) => {
        this.$rootScope.$broadcast('comms-message-statechanged', { messageId: messageId });
    };

    this.proxy.client.broadcastScheduledMessageDeletedEvent = (messageId: number) => {
        this.$rootScope.$broadcast('comms-message-deleted', { messageId: messageId });
    };

    //geotriggered messages
    this.proxy.client.broadcastGeoMessageCreatedEvent = (messageId: number) => {
        this.$rootScope.$broadcast('comms-geomessage-created', { messageId: messageId });
    };

    this.proxy.client.broadcastGeoMessageUpdatedEvent = (messageId: number) => {
        this.$rootScope.$broadcast('comms-geomessage-updated', { messageId: messageId });
    };

    this.proxy.client.broadcastGeoMessageStateChangedEvent = (messageId: number) => {
        this.$rootScope.$broadcast('comms-geomessage-statechanged', { messageId: messageId });
    };

    this.proxy.client.broadcastGeoMessageDeletedEvent = (messageId: number) => {
        this.$rootScope.$broadcast('comms-geomessage-deleted', { messageId: messageId });
    };

    var promise = $.connection.hub.start();
    promise.done(function () {
        //console.log('comms signalr hub started');
    });
    return promise;
}

    public RegisterScheduledMessageCreated(messageId: number): void{
        this.proxy.server.registerScheduledMessageCreated(messageId);
    }

    public RegisterScheduledMessageUpdated(messageId: number): void {
        this.proxy.server.registerScheduledMessageUpdated(messageId);
    }

    public RegisterScheduledMessageDeleted(messageId: number): void {
        this.proxy.server.registerScheduledMessageDeleted(messageId);
    }

    public RegisterScheduledMessageStateChanged(messageId: number): void {
        this.proxy.server.registerScheduledMessageStateChanged(messageId);
    }

    public RegisterGeoMessageCreated(messageId: number): void {
        this.proxy.server.registerGeoMessageCreated(messageId);
    }

   public RegisterGeoMessageUpdated(messageId: number): void {
       this.proxy.server.registerGeoMessageUpdated(messageId);
    }

    public RegisterGeoMessageDeleted(messageId: number): void {
        this.proxy.server.registerGeoMessageDeleted(messageId);
    }

    public RegisterGeoMessageStateChanged(messageId: number): void {
        this.proxy.server.registerGeoMessageStateChanged(messageId);
    }
}

每当我运行karma时,我在命令行中不断看到的错误是forge.communications.CommsApp遇到声明异常FAILED
TypeError:无法在CommsSignalREventService中读取未定义的属性“client”,这意味着CommsSignalREventService.ts文件中的“proxy”变量未定义:

this.proxy = $.connection['communicationsCenterHub'];
console.log('proxy', this.proxy); //resolves to UNDEFINED in tests, works fine in the app

this.proxy.client.broadcastScheduledMessageCreatedEvent = function (messageId) {
        _this.$rootScope.$broadcast('comms-message-created', { messageId: messageId });
    };

我会感激任何帮助,因为在这个阶段,我试图弄清楚它的时间是多么荒谬.

解决方法:

我认为您的问题是您的实际应用程序引用了SignalR在运行时动态生成的JavaScript.该脚本通常位于“〜/ signalr / hubs”或“〜/ signalr / js”.

此脚本为您创建$.connection [‘communicationsCenterHub’]代理.如果在测试中没有引用此脚本,则此代理将是未定义的.

我假设您在运行Jasmine测试时没有运行SignalR服务器.如果是这种情况,您有两种选择:

>您只需将SignalR在“〜/ signalr / hubs”生成的脚本复制到文件中并在测试中引用该文件即可.您可以通过将浏览器指向生成的脚本URL来手动执行此操作,但是您必须在集线器更改时随时更新此文件.您可以通过运行signalr.exe ghp / path:[包含您的Hub类的.dll的路径]作为后期构建步骤来生成此文件.
>您可以完全避免使用生成的代理.查看SignalR JS API reference的“没有生成的代理”部分.

上一篇:javascript – 连接启动后连接到SignalR Hub


下一篇:javascript – SignalR,每个事件有多个事件处理程序