mardi 6 octobre 2015

AngularJS Testing with Mocha and Sinon - Mocking Firebase Dependencies

I am trying to skip going to Firebase for my data in my tests, and return some simple results instead. I do not want to test that the Firebase code works, but that my factories work in returning data.

I have the following factories:

// Get Firebase Reference
angular.module('MyApp').factory('FireBaseData', function(FIREBASE) {
    var FireBaseReference = new Firebase(FIREBASE.URL);  // FIREBASE.URL = xxx.firebaseio.com
    return FireBaseReference;
})

// Get the Firebase Array of Team Records
angular.module('MyApp').factory('AllTeams', ["FireBaseData",    "$firebaseArray",
    function(FireBaseData, $firebaseArray)  {
        return $firebaseArray(FireBaseData.child('Teams'));
    }
]);

I have created mocks that replace the individual functions, and my tests will use these.

'use strict';

var $MockFirebaseArray = function(ArrayWithData) {
    return ArrayWithData;
};

var $MockFirebaseObject = function(ObjectWithData) {
    return ObjectWithData;
};

var MockFirebaseData = function() {
    return {
        child: function(StringValue) {
            return "";
        }
    };
};

Tests with the mocks:

'use strict';

describe('Firebase Mocks', function() {
    var TestArray = [
        { 'aString': 'alpha', 'aNumber': 1, 'aBoolean': false   },
        { 'aString': 'bravo', 'aNumber': 2, 'aBoolean': true },
        { 'aString': 'charlie', 'aNumber': 3, 'aBoolean': true },
        { 'aString': 'delta', 'aNumber': 4, 'aBoolean': true },
        { 'aString': 'echo', 'aNumber': 5 }
    ];

    describe('MockFirebaseData', function() {
        var TestFirebase = MockFirebaseData();
        it('should return empty text ("") from FireBaseData', function() {
            assert.equal('', TestFirebase.child('SomeNode'));
        });
    });

    describe('$MockFirebaseArray', function() {
        it('should have the data array passed', function() {
            var TestData = $MockFirebaseArray(TestArray);
            assert.equal(TestArray.length, TestData.length);
        });
    });

    describe('$MockFirebaseObject', function() {
        it('should have the data object passed', function() {
            var TestData = $MockFirebaseObject(TestArray[0]);
            assert.equal(TestArray[0].length, TestData.length);
            assert.deepEqual(TestArray[0], TestData);
        });
    });
});

This shows that the Mocks are working to return data, which is what I want to stay away from actually accessing Firebase. Now, when I try to use my factory in a test, I am getting errors.

Test the Factory:

describe('Teams Module', function() {
    beforeEach(module('MyApp'));        // Load My Application

    describe('AllTeams Array', function() {
        // Create Test Data
        var TeamData = [
            { "Key": 1, "Name":"Team 1", "Logo": "Team1.jpg" },
            { "Key": 3, "Name":"Team 3", "Logo": "Team3.jpg" },
            { "Key": 2, "Name":"Team 2", "Logo": "Team2.jpg" },
        ];

        beforeEach(function () {
            module(function($provide) {
                var MockData = MockFirebaseData();
                $provide.value('FireBaseData', MockData);
                $provide.value('$firebaseArray', $MockFirebaseArray(TeamData));
            });
        });

        it('can get an instance of AllTeams factory', inject(function(AllTeams) {
            assert.isDefined(AllTeams);
        }));
    });
});

Error returned:

PhantomJS 1.9.8 (Windows 7 0.0.0) 
Teams Module 
AllTeams Array 
can get an instance of AllTeams factory FAILED
TypeError: '[object Object],[object Object],[object Object]' is not a function (evaluating '$firebaseArray(FireBaseData.child('Teams'))')
    at app/Team.js:9

Aucun commentaire:

Enregistrer un commentaire