silintzir
silintzir

Reputation: 792

Karma testing lodash Factory

i have created a factory for the lodash library in my angular app like so:

angular.module('lodash',[]).service('_', function(){
    var _ = window._;
    // i am delete the _ property on the window
    // so that i m enforced to dependency inject
    // lodash each time i want to use it
    // instead of using the global lodash library
    delete window._;
    return _;
});

Now I want to test my module service and i m using the following test

describe('lodash', function() {
    // load the utilities module
    beforeEach(module('lodash'));

    describe('_', function() {
        it('should be defined', inject(function(_) {
            expect(_).not.toBe(null);
        }));
        it('should have toArray() defined', inject(function(_) {
            expect(_.toArray).toBeDefined();
        }));
    });
});

This 2nd test is not succeeding. The only way to make that work is to take away the following line from my service implementation.

delete window._;

My question comes here: Since delete operator only deletes the property from the window object and not the original reference why does deleting window._ break the test and the _ object comes empty in the tests?

Upvotes: 2

Views: 2146

Answers (2)

Андрей
Андрей

Reputation: 411

After each test you jast need to return back $window._
This code should work correctly:

describe('lodash', function() {
    var factory;

    // load the utilities module
    beforeEach(module('lodash'));

    beforeEach(inject(function (___) {
        factory = ___;
    }));

    afterEach(inject(function (_$window_) {
        _$window_._= factory;
    }));

    describe('_', function() {
        it('should be defined', function() {
            expect(factory).toBeDefined();
        });

        it('should have toArray() defined', function () {
            expect(factory.toArray).toBeDefined();
        });

        it('default keys method ->', function () {
            expect(factory.keys({"key1": "value1", "key2": "value2", "key3": "value3"})).toEqual(["key1","key2","key3"]);
        });
    });
});

Upvotes: 1

Morphilos
Morphilos

Reputation: 157

I remember having similar problem. Not sure if the problem is exactly the same, but I solved it copying the properties of lodash in a new object, which I then returned from the factory :

function lodash($window) {
    var lodashLib = $window._;
    var _ = {};

    delete( $window._ );

    // Instead of using directly what I got from the window object, I copy its properties
    // I cannot explain why this works better, but it solved the problem for me
    angular.extend(_, lodashLib);

    return _;
}

Secondly, I think you should be careful with testing not.toBe(null), toBeDefined() might be better (there are a lot of really precise ways to test things with Jasmine). Lastly, for your second test, I believe the proper test should be expect(typeof _.toArray).toBe('function');, which is a bit more specific than just being defined :)

I hope I answered your question, even if my knowledge of unit tests is in general pretty lackluster.

Upvotes: 1

Related Questions