Testing
This guide covers testing strategies for applications using the YouVersion Bible Client.
Unit Testing
Mocking API Calls
Mock the client for unit tests:
from unittest.mock import AsyncMock, patch
import pytest
from youversion.clients import AsyncClient
@pytest.mark.asyncio
async def test_verse_of_the_day():
with patch('youversion.clients.AsyncClient') as mock_client_class:
# Create mock client
mock_client = AsyncMock()
mock_votd = type('Votd', (), {
'day': 1,
'usfm': ['JHN.3.16'],
'image_id': None
})()
mock_client.verse_of_the_day.return_value = mock_votd
mock_client_class.return_value.__aenter__.return_value = mock_client
# Test
async with AsyncClient() as client:
votd = await client.verse_of_the_day()
assert votd.day == 1
assert votd.usfm == ['JHN.3.16']
Testing SyncClient
Test synchronous client:
from unittest.mock import patch, MagicMock
from youversion.clients import SyncClient
def test_sync_client():
with patch('youversion.clients.SyncClient') as mock_client_class:
mock_client = MagicMock()
mock_votd = type('Votd', (), {
'day': 1,
'usfm': ['JHN.3.16']
})()
mock_client.verse_of_the_day.return_value = mock_votd
mock_client_class.return_value.__enter__.return_value = mock_client
with SyncClient() as client:
votd = client.verse_of_the_day()
assert votd.day == 1
Integration Testing
Testing with Real API
For integration tests, use real API calls:
import pytest
from youversion.clients import AsyncClient
@pytest.mark.integration
@pytest.mark.asyncio
async def test_real_api_call():
"""Test with real API (requires valid credentials)."""
async with AsyncClient() as client:
votd = await client.verse_of_the_day()
assert votd is not None
assert votd.day is not None
assert votd.usfm is not None
Fixtures
Create Pytest Fixtures
Create reusable test fixtures:
import pytest
from unittest.mock import AsyncMock
from youversion.clients import AsyncClient
@pytest.fixture
def mock_async_client():
"""Create a mock AsyncClient."""
mock_client = AsyncMock()
mock_votd = type('Votd', (), {
'day': 1,
'usfm': ['JHN.3.16']
})()
mock_client.verse_of_the_day.return_value = mock_votd
return mock_client
@pytest.mark.asyncio
async def test_with_fixture(mock_async_client):
with patch('youversion.clients.AsyncClient') as mock_class:
mock_class.return_value.__aenter__.return_value = mock_async_client
async with AsyncClient() as client:
votd = await client.verse_of_the_day()
assert votd.day == 1
Test Data
Create Test Data Helpers
Create helpers for test data:
def create_mock_moment(**kwargs):
"""Create a mock moment for testing."""
defaults = {
'id': '123',
'kind_id': 'highlight',
'moment_title': 'Test Highlight',
'time_ago': 'just now',
'owned_by_me': True
}
defaults.update(kwargs)
return type('Moment', (), defaults)()
def test_moment_processing():
moment = create_mock_moment(id='456', moment_title='Custom')
assert moment.id == '456'
assert moment.moment_title == 'Custom'
Best Practices
Mock External Dependencies: Always mock API calls in unit tests
Test Error Cases: Test error handling and edge cases
Use Fixtures: Create reusable test fixtures
Separate Unit and Integration Tests: Mark integration tests appropriately
Test Both Clients: Test both AsyncClient and SyncClient