2015-09-28 9 views
1

Я работаю над добавлением модульного тестирования в рамки приложения, и все идет хорошо. Однако я столкнулся с проблемой тестирования, если токен истек или все еще активен.Идентификатор входа в систему

Я смог проверить, был ли пользовательский токен создан, издеваясь над ответом на мой/логин-вызов с токеном, который я сохранил для тестового пользователя, однако это работает только до истечения срока действия токена. У меня нет возможности вручную истечь токен или сбросить время истечения срока действия в будущем.

Мой Auth завод:

auth.isLoggedIn = function(){ 
    var token = SS.getObj('appToken'); 
    if(token){ 
     var payload = JSON.parse($window.atob(token.split('.')[1])); 
     return payload.exp > Date.now()/1000; 
    } else { 
     return false; 
    } 
}; 

И мой юнит-тесты:

describe('auth.isLoggedIn()', function() { 
    it('should return false if a user is not logged in', function() { 
     expect(auth.isLoggedIn()).toEqual(false); // This test passes 100% 
    }); 

    it('should return true if a user is logged in', function() { 
     user = { 
     email: '[email protected]', 
     password: 'password123' 
     }; 
     $httpBackend.expectPOST('/login').respond({ token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6NywiZW1haWwiOiJid2F5bmVAd2F5bmVlbnRlcnByaXNlLmNvbSIsIm5hbWUiOiJCcnVjZSBXYXluZSIsImV4cCI6MTQzODI4NDYwNywiaWF0IjoxNDM4MjgxMDA3fQ.2rpGJ1c5dVi1EiPo0C5JIdva7MonutCYmotP5-pB_N4' }); // I copied a valid token from a test user, but I can't change it since I'm just copying an old token. 
     auth.login(user); 
     $httpBackend.flush(); 
     expect(auth.isLoggedIn()).toEqual(true); // This test passes if the above token has a valid time/date, however I can't set the time/date so it usually fails 
    }); 

    it('should return false if a users token has expired', function() { 
     user = { 
     email: '[email protected]', 
     password: 'password123' 
     }; 
     $httpBackend.expectPOST('/login').respond({ token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6NywiZW1haWwiOiJid2F5bmVAd2F5bmVlbnRlcnByaXNlLmNvbSIsIm5hbWUiOiJCcnVjZSBXYXluZSIsImV4cCI6MTQzODI4NDYwNywiaWF0IjoxNDM4MjgxMDA3fQ.2rpGJ1c5dVi1EiPo0C5JIdva7MonutCYmotP5-pB_N4' }); 
     auth.login(user); 
     $httpBackend.flush(); 
     expect(auth.isLoggedIn()).toEqual(false); // This test fails if the date/time has expired, again I can't set that so it's usually passing, as the token has expired. 
    }); 
    }); 

Я подозреваю, что правильный способ сделать это на самом деле создать действительный маркер во время теста, но я не уверен, как это сделать, поскольку он обрабатывается сервером узлов, ответы которого я макет, чтобы не полагаться на ответ сервера в моих тестах.

+0

ли контролирует ваше приложение истечение токена? Разве это не ответственность сервера? –

+0

Сервер создает токен и истекает срок действия 30 минут в будущем, а затем возвращает токен в приложение. Если токен не обновляется в течение 30 минут, он истек и больше не действует. Мое приложение просто проверяет, истек ли токен перед отправкой запроса на сервер, если оно истекло, приложение направляет пользователя к логину, так как запрос, который пытается сделать, будет отклонен сервером. Как только они войдут в систему и имеют действительный токен, их первоначальный запрос будет завершен. Это предотвращает бомбардировку моего сервера запросами от недопустимых пользователей. – efarley

ответ

1

У меня нет возможности вручную выпустить токен или сбросить время истечения срока действия в будущем.

К счастью, у вас есть хороший способ сделать это и сделать это утверждение: return payload.exp > Date.now()/1000; более предсказуемым. Жасмин имеет довольно приятная особенность издеваться Date объект, и вы можете использовать его следующим образом:

beforeEach(function() { 
    jasmine.clock().install(); 
    jasmine.clock().mockDate(new Date(2015, 8, 28)); //You can set any date 
}); 

afterEach(function() { 
    jasmine.clock().uninstall(); //Don't forget to uninstall your mock 
}); 

С таким подходом вы можете реорганизовать тесты на что-то вроде этого:

it('should return true if a user is logged in', function() { 
    jasmine.clock().install(); 
    jasmine.clock().mockDate(new Date(2015, 8, 28)); //Here you should set some VALID date for token, which you're defining below 

    user = { 
    email: '[email protected]', 
    password: 'password123' 
    }; 
    $httpBackend.expectPOST('/login').respond({ token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6NywiZW1haWwiOiJid2F5bmVAd2F5bmVlbnRlcnByaXNlLmNvbSIsIm5hbWUiOiJCcnVjZSBXYXluZSIsImV4cCI6MTQzODI4NDYwNywiaWF0IjoxNDM4MjgxMDA3fQ.2rpGJ1c5dVi1EiPo0C5JIdva7MonutCYmotP5-pB_N4' }); // I copied a valid token from a test user, but I can't change it since I'm just copying an old token. 
    auth.login(user); 
    $httpBackend.flush(); 
    expect(auth.isLoggedIn()).toEqual(true); // This test passes if the above token has a valid time/date, however I can't set the time/date so it usually fails 

    jasmine.clock().uninstall(); //Clean up 
}); 

it('should return false if a users token has expired', function() { 
    jasmine.clock().install(); 
    jasmine.clock().mockDate(new Date(2020, 11, 30)); //Here you should set some INVALID date for token, which you're defining below 
    user = { 
    email: '[email protected]', 
    password: 'password123' 
    }; 
    $httpBackend.expectPOST('/login').respond({ token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6NywiZW1haWwiOiJid2F5bmVAd2F5bmVlbnRlcnByaXNlLmNvbSIsIm5hbWUiOiJCcnVjZSBXYXluZSIsImV4cCI6MTQzODI4NDYwNywiaWF0IjoxNDM4MjgxMDA3fQ.2rpGJ1c5dVi1EiPo0C5JIdva7MonutCYmotP5-pB_N4' }); 
    auth.login(user); 
    $httpBackend.flush(); 
    expect(auth.isLoggedIn()).toEqual(false); // This test fails if the date/time has expired, again I can't set that so it's usually passing, as the token has expired. 

    jasmine.clock().uninstall(); //Clean up 
}); 

Теперь, как вы можно увидеть, мы можем вручную установить прошлую или будущую дату для функции Date.now(), когда это необходимо.

See Jasmine Clock section with an example.


Вы также можете издеваться Date.now традиционным способом с spyOn:

spyOn(Date, 'now').and.returnValue(2000); 

Это будет выглядеть немного немного чище:

it('should return false if a users token has expired', function() { 
    spyOn(Date, 'now').and.returnValue(2000); //Here you should set some INVALID count of milliseconds for token, which you're defining below 
    user = { 
    email: '[email protected]', 
    password: 'password123' 
    }; 
    $httpBackend.expectPOST('/login').respond({ token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6NywiZW1haWwiOiJid2F5bmVAd2F5bmVlbnRlcnByaXNlLmNvbSIsIm5hbWUiOiJCcnVjZSBXYXluZSIsImV4cCI6MTQzODI4NDYwNywiaWF0IjoxNDM4MjgxMDA3fQ.2rpGJ1c5dVi1EiPo0C5JIdva7MonutCYmotP5-pB_N4' }); 
    auth.login(user); 
    $httpBackend.flush(); 
    expect(auth.isLoggedIn()).toEqual(false); // This test fails if the date/time has expired, again I can't set that so it's usually passing, as the token has expired. 
}); 
+0

Это издевается над новой датой в моем модульном тесте, однако Date.now() вызывается на моем автозаводе, после некоторого тестирования я обнаружил, что Date.now() внутри фабрики auth все еще возвращает текущую дату/время, а не фальшивую дату/время, возвращаемое модульным тестом, чтобы тест по-прежнему не срабатывал. – efarley

+0

@efarley, это странно, потому что в моих тестах Date.now() возвращает посмеянную дату. Какую версию Jasmine вы используете? Вы можете попробовать насмехаться, особенно 'now', от' Date'. См. Мой обновленный ответ. –

+0

Похоже, вы пропустили мой комментарий, посмеянная дата работает в моем тесте, проблема в том, что Date.now() находится в моем файле угловых сервисов, а не в моих тестах. Установка даты в тесте не помогает, когда служба проверяет реальную дату. Мне нужен способ подтолкнуть насмешливую дату из моего теста и в мою службу, где он используется. Date.now() не называется нигде в тесте, это само. – efarley

Смежные вопросы