Jasmine,AngularJS 注入后更改注入的模拟对象

Jasmine, AngularJS change injected mock object after injection

我想在不同情况下测试我的工厂,例如没有令牌、过期令牌和良好令牌。我在模拟 $window.localStorage 时遇到了麻烦。这是我的测试代码:

   describe('Unit: Security Module', function () {

describe('Security factory', function() {
    var windowMock, locationMock, security, $httpBackend, $http, $window, $location;

    beforeEach(module('app.common.security', function($provide) {
        locationMock = {
            url: jasmine.createSpy().and.returnValue(true)
        };
        windowMock = {
            localStorage: { token: false }
        };
        $provide.value('$location', locationMock);
        $provide.value('$window', windowMock);
    }));

    beforeEach(inject(function(_$httpBackend_, _$window_, _$location_, _security_) {
        $httpBackend = _$httpBackend_;
        $window = _$window_;
        $location = _$location_;
        security = _security_;
    }));

    it("Should call location.url with '/login' if no token in localStorage", function() {
        security.tokenCheck();
        expect($location.url).toHaveBeenCalledWith('/login');
    });

    it("Should call location.url with '/login' and delete token if bad token", function() {
        // Need to modify the windowMock.localStorage.token value here somehow

        $httpBackend
            .whenPOST('/api/tokenCheck', {token:"mockBadToken123"})
            .respond (400, "Token invalid or undefined");

        security.tokenCheck();
        expect($location.url).toHaveBeenCalledWith('/login');
        expect($window.localStorage.token).toBeUndefined();
    });

});

});

我的问题是:如果我想修改 windowMock 值,是否必须像这样编写所有测试?

    it("good token", function () {

    module('app.common.security', function ($provide) {
        locationMock = {
            url: jasmine.createSpy().and.returnValue(true)
        };
        windowMock = {
            localStorage: { token: "mockBadToken123" }
        };
        $provide.value('$location', locationMock);
        $provide.value('$window', windowMock);
    });

    inject(function (_$httpBackend_, _$window_, _$location_, _security_) {
        $httpBackend = _$httpBackend_;
        $window = _$window_;
        $location = _$location_;
        security = _security_;
    })

    $httpBackend
        .whenPOST('/api/tokenCheck', {token: "mockBadToken123"})
        .respond(400, "Token invalid or undefined");

    security.tokenCheck();
    expect($location.url).toHaveBeenCalledWith('/login');
    expect($window.localStorage.token).toBeUndefined();


});

或者有更高效的方法吗?

编辑: 工厂本身看起来像这样:

angular.module('app.common.security').factory('security', ['$http', '$window', '$location', function ($http, $window, $location) {

var Security = {};

Security.tokenCheck = function () {

    if (!$window.localStorage.token) {
        $location.url('/login');
        return;
    }

    $http.post('/api/tokenCheck', {token: $window.localStorage.token})
        .success(function (data) {
            console.log("STUBB: set user data, login status and redirect to panel");
        }).error(function (err) {
            delete $window.localStorage.token;
            $location.url('/login');
        });

};

return Security;

}]);

为什么你在考试中没有按照你说的去做?

it("Should call location.url with '/login' and delete token if bad token", function() {
  // Need to modify the windowMock.localStorage.token value here somehow            

  $window.localStorage = { token: "mockBadToken123" };
  $location.url = jasmine.createSpy().and.returnValue(true);

  $httpBackend
        .whenPOST('/api/tokenCheck', {token:"mockBadToken123"})
        .respond (400, "Token invalid or undefined");

  security.tokenCheck();
  $httpBackend.flush();
  expect($location.url).toHaveBeenCalledWith('/login');
  expect($window.localStorage.token).toBeUndefined();
});