unit-testing - 在单元测试中模拟我自己的服务

标签 unit-testing mocking angularjs

我有一项服务将我的其他几个服务作为依赖项。我如何模拟它进行单元测试?

myApp.factory('serviceToTest',
           ['serviceDependency',
    function(serviceDependency) {
        return function(args) {
            return cond(args) ? serviceDependency() : somethingElse();
        };
    }
]);

在上面的例子中,我想模拟出 serviceDependency所以我可以验证它是否被调用。我怎样才能做到这一点?

我可以在测试中执行以下操作:
describe("Services", function() {
    describe('serviceToTest', function() {

        myApp.factory('serviceDependency', function() {
            var timesCalled = 0;
            return function() {
                return timesCalled++;
            }
        });

        it('should do foo', inject(function(serviceToTest, serviceDependency) {
            serviceToTest(["foo", "bar", "baz"]);
            expect(serviceDependency()).to.equal(1);
        });
    });
});

这适用于需要模拟的测试,但它会影响随后所有其他测试的状态,这显然是一个问题。

最佳答案

如果我理解正确,您想测试一个依赖于另一个服务的服务并模拟每个测试的依赖关系。如果是这样,假设我们有一个 car依赖于 engine :

var app = angular.module('plunker', [])
  .factory('car', function(engine) {
     return {
       drive : function() {
         return 'Driving: ' + engine.speed();
       }
     }
  })
  .value('engine', {
    speed : function() {
      return 'fast';
    }
  });

然后你想测试一辆汽车并模拟一个引擎。有两种方法可以做到这一点:或者通过定义一个新模块,我们可以在其中重新定义一个引擎:
describe('Testing a car', function() {
  var testEngine;

  beforeEach(function(){
    testEngine = {};
    angular.module('test', ['plunker']).value('engine', testEngine);
    module('test');
  });   

  it('should drive slow with a slow engine', inject(function(car) {
    testEngine.speed = function() {
      return 'slow';
    };
    expect(car.drive()).toEqual('Driving: slow');
  }));
});

在这里工作的笨蛋:http://plnkr.co/edit/ueXIzk?p=preview

一个更简单的替代方案,基于 JavaScript 的动态特性:
describe('Testing a car', function() {
  var testEngine;

  beforeEach(module('plunker'));
  beforeEach(inject(function(engine){
    testEngine = engine;
  }));

  it('should drive slow with a slow engine', inject(function(car) {
    testEngine.speed = function() {
      return 'slow';
    };
    expect(car.drive()).toEqual('Driving: slow');
  }));
});

http://plnkr.co/edit/tlHnsJ?p=preview

另一种选择是使用 Jasmine 的 spy :
describe('Testing a car', function() {
  var testEngine;

  beforeEach(module('plunker'));
  beforeEach(inject(function(engine){
    testEngine = engine;
  }));

  it('should drive slow with a slow engine', inject(function(car) {
    spyOn(testEngine, 'speed').andReturn('slow');
    expect(car.drive()).toEqual('Driving: slow');
  }));
});

http://plnkr.co/edit/K4jczI?p=preview

关于unit-testing - 在单元测试中模拟我自己的服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13592259/

相关文章:

java - 无法在 Spring Boot 中运行任何单元测试

unit-testing - 测试 Web 应用程序的 UI?

javascript - AngularJS 指令限制 A 与 E

javascript - ASP.NET MVC 应用程序中的 Angular 路由

c# - 从同一方法模拟两个不同的结果

python - 模拟具有特定返回值的实例方法?

python - 如何模拟在 with 语句中使用的 open (使用 Python 中的 Mock 框架)?

c# - 设置 Moq 以忽略虚拟方法

unit-testing - 如何在Groovy/Grails中模拟obj。&method

java - HTTP 状态 415 – 不支持的媒体类型错误