Skip to content

Latest commit

 

History

History
214 lines (175 loc) · 8.04 KB

test_lazy_load_class.md

File metadata and controls

214 lines (175 loc) · 8.04 KB

Lazy-Loaded Class Test Suite Template

Description

This test suite template provides comprehensive tests for a Python class that employs lazy-loading, covering initialization, dependency injection, logging, error handling, and validation using Pydantic. It ensures the class works as expected in various scenarios.

Code Example

import pytest
from unittest.mock import Mock, patch, AsyncMock
from lazy_loaded_class import LazyLoadedClass, ExampleModel  # Replace with the correct module path
import logging

# Fixtures for mocking dependencies
@pytest.fixture
def mock_dependent_class1():
    mock = Mock()
    mock.some_method = Mock(return_value="result_from_dependent_class1")
    mock.to_dict = Mock(return_value={"dependent_class1_data": "value"})
    return mock

@pytest.fixture
def mock_dependent_class2():
    mock = Mock()
    mock.another_method = Mock(return_value="result_from_dependent_class2")
    mock.to_dict = Mock(return_value={"dependent_class2_data": "value"})
    return mock

@pytest.fixture
def mock_logger():
    with patch('logging.getLogger') as mock_get_logger:
        mock_logger_instance = Mock(spec=logging.Logger)
        mock_get_logger.return_value = mock_logger_instance
        yield mock_logger_instance

@pytest.fixture
def valid_input_data():
    return {
        "param1": "example_value",
        "param2": 42
    }

@pytest.fixture
def lazy_loaded_class(valid_input_data):
    return LazyLoadedClass(**valid_input_data)

# Test cases

def test_initialization(lazy_loaded_class, valid_input_data):
    """Test that LazyLoadedClass initializes correctly with given parameters."""
    assert lazy_loaded_class.param1 == valid_input_data["param1"]
    assert lazy_loaded_class.param2 == valid_input_data["param2"]
    assert lazy_loaded_class._dependent_class1 is None
    assert lazy_loaded_class._dependent_class2 is None
    assert lazy_loaded_class._logger is None

def test_logger_lazy_loading(lazy_loaded_class, mock_logger):
    """Test that logger is lazily loaded upon first access."""
    # Before accessing, logger should be None
    assert lazy_loaded_class._logger is None

    # Access logger property
    logger = lazy_loaded_class.logger

    # After access, logger should be initialized
    assert logger is not None
    assert logger == mock_logger
    logger.debug.assert_called_with("Logger initialized for LazyLoadedClass")

@patch('lazy_loaded_class.DependentClass1')
def test_dependent_class1_lazy_loading(mock_dependent_class1_class, lazy_loaded_class):
    """Test that DependentClass1 is lazily loaded upon first access."""
    mock_instance = mock_dependent_class1_class.return_value

    # Before accessing, _dependent_class1 should be None
    assert lazy_loaded_class._dependent_class1 is None

    # Access dependent_class1 property
    dependent_class1 = lazy_loaded_class.dependent_class1

    # After access, _dependent_class1 should be initialized
    assert dependent_class1 is not None
    assert dependent_class1 == mock_instance
    mock_dependent_class1_class.assert_called_once()
    lazy_loaded_class.logger.debug.assert_called_with("DependentClass1 initialized")

@patch('lazy_loaded_class.DependentClass2')
def test_dependent_class2_lazy_loading(mock_dependent_class2_class, lazy_loaded_class):
    """Test that DependentClass2 is lazily loaded upon first access."""
    mock_instance = mock_dependent_class2_class.return_value

    # Before accessing, _dependent_class2 should be None
    assert lazy_loaded_class._dependent_class2 is None

    # Access dependent_class2 property
    dependent_class2 = lazy_loaded_class.dependent_class2

    # After access, _dependent_class2 should be initialized
    assert dependent_class2 is not None
    assert dependent_class2 == mock_instance
    mock_dependent_class2_class.assert_called_once()
    lazy_loaded_class.logger.debug.assert_called_with("DependentClass2 initialized")

def test_some_method(
    lazy_loaded_class,
    mock_dependent_class1,
    mock_dependent_class2,
    mock_logger
):
    """Test the some_method functionality with mocked dependencies."""
    # Inject mocked dependencies
    lazy_loaded_class._dependent_class1 = mock_dependent_class1
    lazy_loaded_class._dependent_class2 = mock_dependent_class2
    lazy_loaded_class._logger = mock_logger

    # Call the method under test
    result = lazy_loaded_class.some_method()

    # Assertions
    mock_dependent_class1.some_method.assert_called_once()
    mock_dependent_class2.another_method.assert_called_once()
    mock_logger.info.assert_called_with("Successfully called methods on lazy-loaded classes")
    assert result == {
        "result1": "result_from_dependent_class1",
        "result2": "result_from_dependent_class2"
    }

def test_to_dict(
    lazy_loaded_class,
    mock_dependent_class1,
    mock_dependent_class2
):
    """Test the to_dict method for correct serialization."""
    # Inject mocked dependencies
    lazy_loaded_class._dependent_class1 = mock_dependent_class1
    lazy_loaded_class._dependent_class2 = mock_dependent_class2

    # Call the method under test
    result = lazy_loaded_class.to_dict()

    # Assertions
    expected_dict = {
        "param1": "example_value",
        "param2": 42,
        "dependent_class1": {"dependent_class1_data": "value"},
        "dependent_class2": {"dependent_class2_data": "value"},
    }
    assert result == expected_dict

def test_add_dependent_class(lazy_loaded_class):
    """Test dynamic addition of dependent classes."""
    mock_new_dependent = Mock()
    lazy_loaded_class.add_dependent_class('dependent_class1', mock_new_dependent)
    assert lazy_loaded_class._dependent_class1 == mock_new_dependent

    lazy_loaded_class.add_dependent_class('dependent_class2', mock_new_dependent)
    assert lazy_loaded_class._dependent_class2 == mock_new_dependent

    with pytest.raises(ValueError) as exc_info:
        lazy_loaded_class.add_dependent_class('invalid_class', mock_new_dependent)
    assert str(exc_info.value) == "Unknown class type: invalid_class"

def test_validate_model_success(lazy_loaded_class):
    """Test successful validation of input data against ExampleModel schema."""
    valid_data = {"id": "123", "value": 10}
    result = lazy_loaded_class.validate_model(valid_data)
    assert isinstance(result, ExampleModel)
    assert result.id == "123"
    assert result.value == 10

def test_validate_model_failure(lazy_loaded_class):
    """Test validation failure when input data does not conform to ExampleModel schema."""
    invalid_data = {"id": "123", "value": "not_an_int"}
    with pytest.raises(ValueError) as exc_info:
        lazy_loaded_class.validate_model(invalid_data)
    assert "Invalid data for ExampleModel" in str(exc_info.value)

def test_error_handling_in_some_method(
    lazy_loaded_class,
    mock_dependent_class1,
    mock_dependent_class2,
    mock_logger
):
    """Test error handling in some_method when dependencies raise exceptions."""
    # Configure mocks to raise exceptions
    mock_dependent_class1.some_method.side_effect = Exception("Error in DependentClass1")
    mock_dependent_class2.another_method.side_effect = Exception("Error in DependentClass2")

    # Inject mocked dependencies
    lazy_loaded_class._dependent_class1 = mock_dependent_class1
    lazy_loaded_class._dependent_class2 = mock_dependent_class2
    lazy_loaded_class._logger = mock_logger

    # Call the method under test
    with pytest.raises(Exception) as exc_info:
        lazy_loaded_class.some_method()

    # Assertions
    assert "Error in DependentClass1" in str(exc_info.value)
    mock_logger.error.assert_called_with("An error occurred in some_method: Error in DependentClass1")

def test_repr(lazy_loaded_class):
    """Test the __repr__ method for correct string representation."""
    expected_repr = "LazyLoadedClass(param1='example_value', param2=42)"
    assert repr(lazy_loaded_class) == expected_repr

def test_str(lazy_loaded_class):
    """Test the __str__ method for correct string output."""
    expected_str = "LazyLoadedClass with param1=example_value and param2=42"
    assert str(lazy_loaded_class) == expected_str

if __name__ == "__main__":
    pytest.main([__file__])