如何在茉莉花单元测试中模拟$ state.params

时间:2015-06-10 05:07:33

标签: angularjs unit-testing jasmine karma-runner karma-jasmine

我有以下控制器EditMeetingCtrl.js

(function() {
    'use strict';

    angular
        .module('myApp')
        .controller('EditMeetingCtrl', EditMeetingCtrl);

    EditMeetingCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$translate',
        'meetingService', 'companyService', 'notificationService', 'meeting'];

function EditMeetingCtrl($rootScope, $scope, $state, $http, $translate, meetingService, companyService, notificationService, meeting) {
        $scope.meeting = meeting;

        $scope.companyId = $state.params.companyId;
        $scope.save = save;


        function save() {
            $scope.buttonDisable = true;
            meetingService.saveMeeting($state.params.companyId, $state.params.meetingId, $scope.meeting)
                .success(function(meetingId) {
                   //more code
                });
        }


}
})();

EditMeetingCtrlSpec.js测试用例

describe('in EditMeetingCtrl', function () {

    var companyService , meetingService ;

    meetingId = 123321 ;                      
    companyId = 456654 ;
    meetingObj = {} ;

    var fakeHttpPromise = {
                            success: function() {}
                          };

    beforeEach(angular.mock.module('myApp'));

    beforeEach(angular.mock.inject(function (_$httpBackend_, _companyService_ , _meetingService_) {
        $httpBackend = _$httpBackend_;
        companyService = _companyService_;
        meetingService = _meetingService_ ;
    }));

    describe('EditMeetingCtrl.save()', function () {
        var $rootScope, scope, $controller , $q  ;

        beforeEach(inject(function ($rootScope, $controller , _meetingService_ ) {
            scope = $rootScope.$new();
            createController = function() {
                return $controller('EditMeetingCtrl', {
                $scope: scope,
                meeting : {} ,
                meetingService : _meetingService_
                }); 
            };
            var controller = new createController();
        }));

        it("should save the meeting object", function() {
            spyOn(meetingService, 'saveMeeting').and.returnValue(fakeHttpPromise);
            scope.save();
            expect(meetingService.saveMeeting).toHaveBeenCalledWith( meetingId , companyId , meetingObj);
        });

    });

});

当尝试运行以下测试casse EditMeetingCtrlSpec.js时,我得到以下测试失败

PhantomJS 1.9.8 (Windows 8) EditMeetingCtrl Spying --> EditMeetingCtrl.save() should save the meeting FAILED
        Expected spy saveMeeting to have been called with [ 123321, 456654, Object({  }) ] but actual calls were [ undef
ined, undefined, Object({  }) ].

因此,了解此问题的方式是,save()方法的服务调用包含$state.params.companyId, $state.params.meetingId个参数,并在调用服务调用时发送undefined个值。因此我需要嘲笑$state.params。不知道该怎么做。谁能指出我正确的方向?

迈克尔拉迪奥诺夫回答后的编辑

describe('EditMeetingCtrl.save()', function () {
        var $rootScope, scope, $controller , $q  , $state ;

        beforeEach(inject(function ($rootScope, $controller , $state , _meetingService_ ) {
            scope = $rootScope.$new();
            createController = function() {
                return $controller('EditMeetingCtrl', {
                $scope: scope,
                meeting : {} ,
                meetingService : _meetingService_
                }); 
            };
            var controller = new createController();
        }));

        it("should save the meeting", function() {
            $state.params = { companyId: 123, meetingId: 567 };
            spyOn(meetingService, 'saveMeeting').and.returnValue(fakeHttpPromise);
            scope.save();
            //expect(meetingService.saveMeeting).toHaveBeenCalledWith( meetingId , companyId , meetingObj);
        });

    });

我已经完成了上述操作,但是我收到以下错误:$ state未定义。

Firefox 38.0.0 (Windows 8.1) In EditMeetingCtrl EditMeetingCtrl.save() should save the meeting FAILED
        TypeError: $state is undefined in C:/Users/sal/Documents/myApp/test/meeting/EditMe
etingCtrlSpec.js (line 80)

我认为这是因为我没有这样做 - >注入方法中的$state : state,所以我也尝试过这样做但得到了同样的错误。我在这里失踪了什么?

1 个答案:

答案 0 :(得分:19)

您可以模拟整个import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class Trie<V> { Entry<V> entry; char key; Map<Character, Trie<V>> children; public Trie() { this.children = new HashMap<Character, Trie<V>>(10); entry = new Entry<V>(); } /** non-public, used by _put() */ Trie(char key) { this.children = new HashMap<Character, Trie<V>>(10); this.key = key; entry = new Entry<V>(); } public void put(String key, V value) { _put(new StringBuffer(key), new StringBuffer(""), value); } void _put(StringBuffer remainder, StringBuffer prefix, V value) { if (remainder.length() > 0) { char keyElement = remainder.charAt(0); Trie<V> t = null; try { t = children.get(keyElement); } catch (IndexOutOfBoundsException e) { } if (t == null) { t = new Trie<V>(keyElement); children.put(keyElement, t); } prefix.append(remainder.charAt(0)); t._put(remainder.deleteCharAt(0), prefix, value); } else { this.entry.value = value; this.entry.prefix = prefix.toString(); } } /** * Retrieves element from prefix table matching as a prefix to provided key. * E.g. is key is "abcde" and prefix table has node "ab" then this call will * return "ab" * * @param key * a string which starts with prefix to be searched in the table * (e.g. phone number) * @return an Object assosiated with matching prefix (i.e if key is a phone * number it may return a corresponding country name) */ public V get(String key) { return _get(new StringBuffer(key), 0); } /** * Returns true if key has matching prefix in the table */ public boolean hasPrefix(String key) { return ((this.get(key) != null) ? true : false); } V _get(StringBuffer key, int level) { if (key.length() > 0) { Trie<V> t = children.get(key.charAt(0)); if (t != null) { V result = t._get(key.deleteCharAt(0), ++level); return result == null ? entry.value : result; } else { return (level > 0) ? entry.value : null; } } else { return entry.value; } } @Override public String toString() { Iterator<Character> it = children.keySet().iterator(); StringBuffer childs = new StringBuffer(); while (it.hasNext()) { Character key = it.next(); childs.append(String.format("\n%s\n", // adding a tab to the beginning of every line to create a visual tree String.format("%s: %s", key, children.get(key)).toString().replaceAll("(?m)(^)", "\t"))); } return String.format("Trie [entry=%s, children=%s]", entry, childs); } static public class Entry<V> { String prefix; V value; public Entry() { } public Entry(String p, V v) { prefix = p; value = v; } public String prefix() { return prefix; } public V value() { return value; } @Override public String toString() { return "Entry [prefix=" + prefix + ", value=" + value + "]"; } } } 提供程序,然后在调用$state之前准确指定您希望在params属性中包含哪些值:

save