如何使用业力在测试文件之间共享模拟?

How to share a mock between test files using karma?

我在一个 angular 应用程序中工作,其中有许多测试文件共享相同的模拟。我想知道如何提取这些模拟并将它们放在一个单独的文件中。

我试图创建一个对象并在我的测试中重用它,但我遇到了一个异常:ReferenceError:找不到变量:require

业力文件:

module.exports = {
  options: {
    frameworks: ['jasmine'],
    preprocessors: {
      '<%= paths.scripts %>/**/*.js': ['coverage']
    },
    reporters: ['progress', 'coverage', 'junit'],
    coverageReporter: {
      dir : '<%= paths.coverage %>',
      reporters: [
        { type: 'html', subdir: 'report-html' },
        { type: 'cobertura', subdir: '.', file: 'code-coverage.xml' },
      ]
    },
    junitReporter: {
      outputFile: '<%= paths.testReport %>/test-results-karma.xml'
    },
    port: 9999,
    colors: true,
    logLevel: 'INFO',
    autoWatch: false,
    browsers: ['PhantomJS'],
    singleRun: true
  },

  portal: {
    options: {
      basePath: 'public/',
      files: [
        'bower_components/angular/angular.js',
        'bower_components/angular-mocks/angular-mocks.js',
        'bower_components/angular-sanitize/angular-sanitize.js',
        'bower_components/angular-bootstrap/ui-bootstrap.js',
        'bower_components/angular-translate/angular-translate.js',
        'bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.js',
        'scripts/<%= paths.module %>',
        'scripts/**/*.js',
        'test/mock/**/*.js',
        'test/spec/unit/**/*.js'
      ]
    }
  }
};

模拟:

var EcMock = (function() {
  'use strict';

  function ecMock() {
    this.dom = {
      addClass: function() {
        return angular.noop();
      },
      getViewportWidth: function() {
        return angular.noop();
      }
    };

    this.detect = {
      geolocation: true
    };
  }

  return ecMock;
})();

module.exports = EcMock;

业力测试文件中的用法:

var EcMock = require('../../../../mock/EcMock');  

我想出了如何以 angular 的方式解决这个问题。评论解释了你必须做什么。

//First step: Make sure you included your mock files in the karm conf file

//Second step: Define a mock service
(function() {
'use strict';

angular.module('mock')
  .factory('myServiceMock', myServiceMock);
  
  function myServiceMock($q) {   
    var methodsToMock = ['myMethod1', 'myMethod2'],
        service = {};
    
    //Create an object with spies already on it. Use one of the approaches below:
    
    //Approach 1: simple methods
    service = jasmine.createSpyObj('myServiceMock', methodsToMock]); 
    
    //Approach 2: promise methods
    angular.forEach(methodsToMock, function(method) {
      service[method] = jasmine.createSpy(method).and.returnValue($q.when({}));
    }); 
    
    return service;
  }
})();

//Third step: Mock service usage
(function() {
'use strict';

describe('Service Test', function() {
  var myServiceMock;
  
  //Load mock module
  beforeEach(module('mock'));

  beforeEach(inject(function(_myServiceMock_) {
    //Get mock service
    myServiceMock = _myServiceMock_;
  }));
  
  describe('Feature Test', function() {
  
    it('should test something', function() {
      //You can return whatever you want from your mock method
      myServiceMock.method1.and.returnValue('Return some value');
    });
  });
});
})();

//Remember you have to tell angular to use your mock service instead of your real one.

//If you're testing a controller:
beforeEach(inject(function(_$controller_, _myServiceMock_) {
    scope = _$rootScope_.$new();
    myServiceMock = _myServiceMock_;

    MyController = _$controller_('MyController', {
      $scope: scope,
      myServiceMock: myServiceMock //Use mock service instead of real one
    });
  }));

//If you're testing another service:
beforeEach(function () {
  module(function($provide) {
    $provide.service('myService', myServiceMock);
  });
});