2015-10-06 49 views
0

我試圖跳過在我的測試中爲我的數據轉至Firebase,並返回一些簡單的結果。我不想測試Firebase代碼的工作原理,但我的工廠可以返回數據。使用摩卡和Sinon進行AngularJS測試 - 嘲笑Firebase依賴關係

我有以下工廠:

// 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')); 
    } 
]); 

我創建模擬,從而取代了各個功能,以及我的測試將使用這些。

'use strict'; 

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

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

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

測試與嘲笑:

'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); 
     }); 
    }); 
}); 

這表明嘲弄正在返回的數據,這是我想從實際訪問火力地堡望而卻步。現在,當我嘗試在測試中使用我的工廠時,出現錯誤。

測試廠:

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); 
     })); 
    }); 
}); 

返回錯誤:

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 
+0

'$ MockFirebaseArray'返回一個數組。但是,在「AllTeams」中,您試圖將其用作函數。 –

+0

@AnidMonsur我試圖修復我的工廠來驗證它返回什麼,因爲我相信$ firebaseArray()調用通常返回數組數據。我正在努力爲我的工廠獲得同樣的東西。也許我的注射是錯誤的?我想驗證我恢復了我所期望的,所以我可以使用相同的結構化模擬與使用AllTeams顯示列表的Controller一起工作。 –

+0

也許你會更好地使用[mockfirebase](https://github.com/katowulf/mockfirebase)模擬Firebase的參考資料,並保留原有的AngularFire方法。 –

回答

1

相反的:

$provide.value('$firebaseArray', $MockFirebaseArray(TeamData)); 

試試這個:

$provide.value('$firebaseArray', $MockFirebaseArray); 

我相信這是你打算首先做的。注入後,您的工廠將能夠呼叫$firebaseArray作爲功能。

+0

這似乎超過了我目前的錯誤。那麼更快的問題就是如何傳遞數據來恢復它?在我的原始行中,發送數組將返回。我想現在檢查我的AllTeams返回3條記錄,以便我可以處理它們。 –

+1

它仍然返回你傳入的內容。但是你傳入一個空字符串,因爲這是'MockData.child()'返回的內容。 –

+0

非常感謝。這正是我所期待的。我的測試現在通過了我的工廠的良好代碼覆蓋。現在我只需要弄清楚如何實際移動mockfirebase庫以允許我測試Firebase添加/刪除工廠功能的其餘部分。 –