在角度服务中测试闭包中的初始化逻辑

时间:2013-12-04 15:36:12

标签: unit-testing angularjs factory

我有一个角度服务,用作工厂函数来实现引擎类型的许多对象实例,如下所示:

angular.module('parts.engine', []).factory('Engine', function() {

    var Engine = function( settings ) {
        this.hp = settings.engine.hp;
        this.miles = 0;
    };
    Engine.prototype.setMiles = function( miles ) { this.miles = miles; }

    return Engine;
});

假设我有另一个角度服务,它也用于创建像这样的对象的实例:

angular.module('car', ['parts.engine']).factory('carCreator', function( Engine ) {

    var carCreator = function( settings ) {

        var engine = new Engine( settings );
        engine.setMiles( settings.engine.miles )

        return {
            brand: settings.brand;
            engine: engine;
        }
    };

    return carCreator;
});

所以我现在实例化这样一个汽车对象的新实例:

angular.module('carApp', ['car']).controller('AppCtrl', function( carCreator ) {

    var settings = {
        brand: 'Ford',
        engine: {
            hp: 125,
            miles: 12000
        }
    };

    var newCar = carCreator(settings);

});

有没有人知道如何测试初始化​​逻辑:

var engine = new Engine( settings );
engine.setMiles( settings.engine.miles )

在carCreator工厂?我知道我可以使用carCreator类实例化一个对象,并检查返回的对象engine.miles属性是否设置为正确的值。但我有一些情况,检查这一点并不容易,因为初始化逻辑和返回的值要复杂得多。我想要做的是在Engine类中测试setMiles的businesslogic,并在测试carCreator类时在Engineengine.setMiles上设置一个SpyOn,但是我该怎么做,在闭包中创建engine时?

1 个答案:

答案 0 :(得分:2)

您可以使用$provide向carCreator提供Engine服务的模拟版本。然后你就可以监视它并断言已经采取了正确的步骤。

其中一个比较棘手的问题是你正在测试一个构造函数,jasmine mocks不能很好地运行,你需要返回一个mockInstance并监视该实例。

var mockEngine, mockEngineInstance, carCreatorService;

beforeEach(function () {
    module('car', function ($provide) {

       // Define a mock instance
       mockEngineInstance = {
           setMiles: function () {}
       }; 

       // Mock the engine service to give a mocked instance
       mockEngine = function () {
           return mockEngineInstance;
       };

       $provide.value('Engine', mockEngine);
    });

    inject(function (carCreator) {
        carCreatorService = carCreator;
    });
});

it('should test that miles are set when a car is created',
    function () {
        // Arrange.
        spyOn(mockEngineInstance, 'setMiles');

        // Act.
        carCreatorService({
            engine: {
                miles: 100
            }
        });

        // Assert.
        expect(mockEngineInstance.setMiles).toHaveBeenCalledWith(100);
    }
);