title: How to mock socket.io with Angular and Jasmine
body: <p>I'm having trouble figuring out how to correctly mock Socket.io in an Angular application using Jasmine and Karma.</p>
  
  <p>Here are the files found in <code>karma.conf.js</code>:</p>
  
  <pre><code>'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'
  </code></pre>
  
  <p>Here is how my controller looks:</p>
  
  <pre><code>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})
          });
      }]);
  </code></pre>
  
  <p>Here is my socket factory:</p>
  
  <pre><code>var lunchrFactories = angular.module('lunchrFactories', []);
  
  lunchrFactories.factory('socket', function (socketFactory) {
      return socketFactory();
  });
  </code></pre>
  
  <p>Here is the main angular module:</p>
  
  <pre><code>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);
      }]);
  </code></pre>
  
  <p>Here is the test I'm having trouble figuring out:</p>
  
  <pre><code>'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
          })
      })
  });
  </code></pre>
  
  <p>I suspect that <code>socket</code> isn't being properly injected and I'm not sure how to fix it. Similarly, I'd also like to be able to expect that a call to <code>socket.emit</code> is made but don't know how.</p>
  
  <p>Any help would be appreciated.</p>
  
  <p>EDIT: I'd like to use <a href="https://github.com/nullivex/angular-socket.io-mock" rel="nofollow">this socket mock</a> if possible but I'm having trouble figuring out exactly how it works.</p>