""" Unit tests for authentication service """ import pytest from unittest.mock import Mock from src.auth.service import AuthService from src.database.models import User from src.database.repositories import UserRepository class TestAuthService: """Test suite for AuthService""" @pytest.fixture def mock_user_repository(self): """Create a mock user repository""" return Mock(spec=UserRepository) @pytest.fixture def auth_service(self, mock_user_repository): """Create an auth service instance with mock repository""" return AuthService(mock_user_repository) def test_hash_password_generates_hash(self, auth_service): """Test that password hashing generates a hash string""" password = "test_password_123" hashed = auth_service.hash_password(password) # Hash should be a string and different from plain password assert isinstance(hashed, str) assert hashed != password assert len(hashed) > 0 def test_hash_password_generates_different_hashes(self, auth_service): """Test that same password generates different hashes (salt)""" password = "test_password_123" hash1 = auth_service.hash_password(password) hash2 = auth_service.hash_password(password) # Different hashes due to salt assert hash1 != hash2 def test_verify_password_succeeds_with_correct_password(self, auth_service): """Test that password verification succeeds with correct password""" password = "correct_password" hashed = auth_service.hash_password(password) assert auth_service.verify_password(password, hashed) is True def test_verify_password_fails_with_incorrect_password(self, auth_service): """Test that password verification fails with incorrect password""" password = "correct_password" wrong_password = "wrong_password" hashed = auth_service.hash_password(password) assert auth_service.verify_password(wrong_password, hashed) is False def test_authenticate_user_succeeds_with_valid_credentials( self, auth_service, mock_user_repository ): """Test that authentication succeeds with valid username and password""" # Setup username = "test_user" password = "test_password" hashed_password = auth_service.hash_password(password) mock_user = User( id=1, username=username, hashed_password=hashed_password, role="User" ) mock_user_repository.get_by_username.return_value = mock_user # Execute result = auth_service.authenticate_user(username, password) # Assert assert result is not None assert result.username == username assert result.role == "User" mock_user_repository.get_by_username.assert_called_once_with(username) def test_authenticate_user_fails_with_invalid_username( self, auth_service, mock_user_repository ): """Test that authentication fails when username doesn't exist""" # Setup mock_user_repository.get_by_username.return_value = None # Execute result = auth_service.authenticate_user("nonexistent", "password") # Assert assert result is None mock_user_repository.get_by_username.assert_called_once_with("nonexistent") def test_authenticate_user_fails_with_invalid_password( self, auth_service, mock_user_repository ): """Test that authentication fails with incorrect password""" # Setup username = "test_user" correct_password = "correct_password" wrong_password = "wrong_password" hashed_password = auth_service.hash_password(correct_password) mock_user = User( id=1, username=username, hashed_password=hashed_password, role="User" ) mock_user_repository.get_by_username.return_value = mock_user # Execute result = auth_service.authenticate_user(username, wrong_password) # Assert assert result is None mock_user_repository.get_by_username.assert_called_once_with(username) def test_authenticate_user_identifies_admin_role( self, auth_service, mock_user_repository ): """Test that authenticated admin user can be identified by role""" # Setup username = "admin_user" password = "admin_password" hashed_password = auth_service.hash_password(password) mock_user = User( id=1, username=username, hashed_password=hashed_password, role="Admin" ) mock_user_repository.get_by_username.return_value = mock_user # Execute result = auth_service.authenticate_user(username, password) # Assert assert result is not None assert result.role == "Admin" assert result.is_admin() is True def test_authenticate_user_identifies_regular_user_role( self, auth_service, mock_user_repository ): """Test that authenticated regular user can be identified by role""" # Setup username = "regular_user" password = "user_password" hashed_password = auth_service.hash_password(password) mock_user = User( id=1, username=username, hashed_password=hashed_password, role="User" ) mock_user_repository.get_by_username.return_value = mock_user # Execute result = auth_service.authenticate_user(username, password) # Assert assert result is not None assert result.role == "User" assert result.is_admin() is False def test_create_user_with_hashed_password( self, auth_service, mock_user_repository ): """Test that creating a user hashes the password""" # Setup username = "new_user" password = "plain_password" role = "User" mock_user = User( id=1, username=username, hashed_password="hashed_value", role=role ) mock_user_repository.create.return_value = mock_user # Execute result = auth_service.create_user_with_hashed_password( username, password, role ) # Assert assert result is not None assert result.username == username # Verify that create was called with a hashed password (not plain text) call_args = mock_user_repository.create.call_args assert call_args[0][0] == username # username assert call_args[0][1] != password # hashed_password should not equal plain password assert call_args[0][2] == role # role