如何使用 Angular 和 Jasmine 模拟 socket.io
Posted
技术标签:
【中文标题】如何使用 Angular 和 Jasmine 模拟 socket.io【英文标题】:How to mock socket.io with Angular and Jasmine 【发布时间】:2015-05-04 22:40:53 【问题描述】:我无法弄清楚如何使用 Jasmine 和 Karma 在 Angular 应用程序中正确模拟 Socket.io。
这是在karma.conf.js
中找到的文件:
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'bower_components/angular-ui-router/release/angular-ui-router.js',
'bower_components/angular-socket-io/socket.js',
'bower_components/socket.io-client/socket.io.js',
'bower_components/angular-socket-io/mock/socket-io.js',
'public/javascripts/*.js',
'ng_tests/**/*.js',
'ng_tests/stateMock.js'
这是我的控制器的外观:
var lunchrControllers = angular.module('lunchrControllers', []);
lunchrControllers.controller('UserMatchingController', ['$state', 'socket',
function ($state, socket)
socket.emit('match');
socket.on('matched', function (data)
$state.go('users.matched', name: data.name)
);
]);
这是我的套接字工厂:
var lunchrFactories = angular.module('lunchrFactories', []);
lunchrFactories.factory('socket', function (socketFactory)
return socketFactory();
);
这是主要的角度模块:
var lunchrApp = angular.module('lunchr', ['ui.router', 'btford.socket-io', 'lunchrControllers', 'lunchrFactories' ]);
lunchrApp.config(['$stateProvider', '$urlRouterProvider', '$locationProvider',
function ($stateProvider, $urlRouterProvider, $locationProvider)
$urlRouterProvider.otherwise('/');
$stateProvider.
state('mainPage',
url: '/',
templateUrl: '/partials/main.jade',
controller: 'MainPageController'
)
.state('users',
url: '/users',
templateUrl: '/partials/users.jade',
controller: 'UserController'
)
.state('users.matching',
url: '/matching',
templateUrl: '/partials/users.matching.jade',
controller: 'UserMatchingController'
)
.state('users.matched',
url: '/matched',
templateUrl: '/partials/users.matched.jade',
params:name:null,
controller: 'UserMatchedController'
)
.state('register',
url:'/register',
templateUrl: 'partials/register.jade',
controller: 'RegisterController'
);
$locationProvider.html5Mode(true);
]);
这是我无法弄清楚的测试:
'use strict';
describe('UserMatchingController', function ()
beforeEach(module('lunchr'));
beforeEach(module('stateMock'));
var $controller, $rootScope, $state, socket;
beforeEach(inject(function ($injector)
// Get hold of a scope (i.e. the root scope)
$rootScope = $injector.get('$rootScope');
$state = $injector.get('$state');
// The $controller service is used to create instances of controllers
$controller = $injector.get('$controller');
socket = $injector('socket');
));
afterEach(function ()
$state.ensureAllTransitionsHappened();
);
function createController()
return $controller('UserMatchingController', '$scope': $rootScope);
describe('on initiazation', function()
it('socket should emit a match', function()
createController();
// would like to be able to expect a socket.emit call
);
it('should transition to users.matched upon receiving matched', function()
createController();
$state.expectTransitionTo('user.matched');
socket.receive('matched', name: 'Ben'); //This errors out with: cannot read property 'receive' of undefined
)
)
);
我怀疑socket
没有正确注入,我不确定如何修复它。同样,我也希望能够期待调用socket.emit
,但不知道如何。
任何帮助将不胜感激。
编辑:如果可能,我想使用this socket mock,但我无法弄清楚它是如何工作的。
【问题讨论】:
【参考方案1】:我会使用Sinon.js 创建一个模拟套接字对象。
例如,在您的beforeEach
中,将套接字初始化为空对象:
socket = ;
createController()
必须将模拟传递给控制器:
$controller('UserMatchingController', '$scope': $rootScope, 'socket': socket);
然后在你的测试中做这样的事情:
socket.emit = sinon.spy(); //Create a spy so we can check if it was called
createController();
expect(socket.emit).toHaveBeenCalledWith('match');
您将需要包sinon 和jasmine-sinon。此外,如果您使用 Karma,则需要 karma-sinon。您可以在各个页面上找到有关设置的更多指南。
编辑:在您的情况下,您的模拟每次都需要具有 on
和 emit
函数,因为控制器需要它们。在这种情况下,最好将其放入beforeEach
函数中:
socket =
emit : sinon.spy(),
on : sinon.spy()
;
【讨论】:
啊,有道理。两个问题:你建议使用诗浓的spy
函数和茉莉花的函数有什么原因吗?另外,我添加的修改会影响您的推荐吗?
您链接的那个模拟需要您创建其中一个,将其作为依赖项传递给控制器,然后在测试后确认发出的哈希包含某些内容。我个人更喜欢使用 sinon。在这种情况下,我只需要知道是否调用了 ton 就使用了 spy。如果您希望它调用回调(例如对于事件),您应该使用sinon.stub().callsArgWith(0, mockData)
。我实际上没有使用过 Jasmine 的间谍,我猜两者都可以。【参考方案2】:
我最终使用了this solution 中定义的sockMock
对象。
【讨论】:
以上是关于如何使用 Angular 和 Jasmine 模拟 socket.io的主要内容,如果未能解决你的问题,请参考以下文章
模拟指令以测试组件 - Angular 8 与 jasmine 和 Karma
如何模拟在 AngularJS Jasmine 单元测试中返回承诺的服务?
在 Jasmine 单元测试中模拟 AngularJS 模块依赖项
使用 jasmine / karma 进行 Angular 4 单元测试和 http post mocking - 如何修复