测试作为构造函数的注入服务

时间:2013-12-04 21:56:20

标签: angularjs testing jasmine

假设我有这样的服务,其中汽车获得注入的引擎服务,这是一个构造函数:

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

    var carCreator = function( settings ) {

        var engineInstance = engine( settings );
        engineInstance.setMiles( settings.engine.miles );

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

    return carCreator;
});

如何在初始化逻辑中测试两行:

var engineInstance = engine( settings );
engineInstance.setMiles( settings.engine.miles )

1:使用engine

调用settings

2:使用engineInstance.setMiles

调用settings.engine.miles

这就是我现在正在做的事情,但没有运气:

describe('initialization', function() {

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

    var mockEngineInstance = {
        setMiles: function() {}
    };

    window.mockEngineCreator = function() {
        return mockEngineInstance;
    }

    beforeEach(module('car', function($provide) {
        $provide.value('engine', mockEngineCreator );
    }));

    beforeEach(inject(function(_carCreator_) {
        carCreator = _carCreator_;
    }));

    it('should init text object correctly on initialization', function() {

        spyOn(window, 'monkEngineCreator');
        spyOn(mockEngineInstance, 'setMiles');
        carCreator( settings );

        expect(window.mockEngineCreator).toHaveBeenCalledWith( settings );
        expect(mockEngineInstance.setMiles).toHaveBeenCalledWith( settings.engine.miles );
    });
});

但是这个测试失败了,说window.mockEngineCreator从未被调用过。似乎$ provide创建了传入函数的新副本,而不是保留对它的引用。那么,有没有人知道如何设置可以正确测试的测试?

1 个答案:

答案 0 :(得分:8)

原因是当你运行spyOn(window,'monkEngineCreator')时,间谍会被放在窗口上,而不是角度用于依赖注入的注入值。

做这样的事情应该有效:(未经测试的代码)

beforeEach(module('car', function($provide){
    $provide.value('engine', jasmine.createSpy('engineSpy').andCallFake(function(){
        return mockEngineInstance;
    }));
}));

it('should init', inject(function(carCreator, engine){
    var settings = {};
    carCreator(settings);

    expect(engine).toHaveBeenCalledWith(settings);
}));