Always use autospec=True or create_autospec() when mocking services, classes, or objects.
# ❌ BAD: Mock allows non-existent methods
mock_service = Mock()
mock_service.get_user_data.return_value = {...} # Typo - no error!
# ✅ GOOD: Autospec catches non-existent methods
mock_service = create_autospec(UserService)
mock_service.get_user_data.return_value = {...} # AttributeError - method doesn't exist!
mock_service.get_user_info.return_value = {...} # Correct method name- Catches typos in method names at test time
- Enforces correct signatures (args, kwargs)
- Tests fail when service API changes
- Prevents testing against phantom methods
- Use
mock.create_autospec(ClassName)for class mocks - Use
@patch('module.Class', autospec=True)for decorators - Use
mocker.patch('module.Class', autospec=True)with pytest-mock
# Service being tested
class InvestmentService:
def get_portfolio_summary(self, user_id: int) -> dict:
"""Get portfolio summary for user"""
pass
# ❌ WITHOUT AUTOSPEC - Test passes but code is broken
def test_portfolio_view_without_autospec(mocker):
# Mock without autospec - anything goes
mock_service = mocker.patch('eshares.investments.services.InvestmentService')
# TYPO in method name - test still passes!
mock_service.return_value.get_portfilio_summary.return_value = {
'total_value': 10000
}
response = client.get('/api/portfolio/123')
# Test passes ✓
# Production breaks ✗ - AttributeError: 'InvestmentService' has no attribute 'get_portfilio_summary'
assert response.status_code == 200
# ✅ WITH AUTOSPEC - Test catches the error
def test_portfolio_view_with_autospec(mocker):
# Mock with autospec - enforces real API
mock_service = mocker.patch(
'eshares.investments.services.InvestmentService',
autospec=True
)
# TYPO in method name - test fails immediately!
mock_service.return_value.get_portfilio_summary.return_value = {
'total_value': 10000
}
# AttributeError: Mock object has no attribute 'get_portfilio_summary'
# Fix the typo:
mock_service.return_value.get_portfolio_summary.return_value = {
'total_value': 10000
}
response = client.get('/api/portfolio/123')
# Test passes ✓
# Production works ✓
assert response.status_code == 200- Service method renamed during refactoring:
calculate_tax()→calculate_tax_liability() - Without autospec: All tests keep passing with old method name
- Production deploys, everything breaks 💥
- With autospec: Tests fail immediately, forcing you to update mocks ✅
Add this to your CLAUDE.md or testing guidelines:
### Mock Safety with Autospec
Always use `autospec=True` or `create_autospec()` when mocking services, classes, or objects to ensure mocks match real APIs and catch refactoring errors early.