-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Problem
During integration testing, Flask's before_request handlers throw AttributeError exceptions when the test routing infrastructure (TestCampusRequest, flask_test.register_test_app) is used. The error occurs because the request object lacks certain attributes expected by the before_request handlers.
Root Cause
The TestCampusRequest class (in tests/flask_test.py) patches campus_python to use Flask's test client for HTTP requests. However:
- Flask test client requests are minimal
Requestobjects campus.auth.routes.__init__.pyhas abefore_requesthandler that callsauthenticate()- The
authenticate()function expects headers and other attributes that may not be present in test requests
Error Trace
WARNING:campus.common.webauth.http:Missing Authorization header. Header keys: ['User-Agent', 'Host']
ERROR:campus.common.errors:APIError in ...campus\common\webauth\http\__init__.py: Missing Authorization header.
Traceback (most recent call last):
File "...\flask\app.py", line 915, in full_dispatch_request
File "...\flask\app.py", line 1291, in preprocess_request
File "...\campus\auth\routes\__init__.py", line 49, in authenticate
...
campus.common.errors.api_errors.UnauthorizedError: Missing Authorization header.
Code Context
campus/auth/routes/__init__.py - the before_request handler:
@app.before_request
def authenticate():
req_header = req.headers.get("Authorization")
if not req_header:
raise api_errors.UnauthorizedError(
message="Missing Authorization header"
)Why This Fails in Tests
- Integration tests intentionally test unauthorized endpoints
- The before_request handler runs BEFORE the test can make assertions about the response
- The errors are logged but tests still pass (exception is caught and handled)
- This creates confusing test output with WARNING/ERROR logs for passing tests
Potential Solutions
-
Add test mode detection to before_request: Skip authentication in test mode
@app.before_request def authenticate(): if os.getenv("ENV") == "testing": return # Skip auth in tests # ... rest of auth logic
-
Configure test apps differently: Use
app.testing = Trueto disable certain error handlers -
Mock authentication in tests: Set up proper auth headers in test requests
-
Add custom error handler in test mode: Suppress UnauthorizedError in test fixtures
-
Conditional before_request registration: Don't register the before_request handler in test mode
Trade-offs
| Solution | Pros | Cons |
|---|---|---|
| Test mode check in before_request | Simple, centralized | Auth code needs test awareness |
| Conditional registration | Cleaner separation of concerns | More complex app setup |
| Mock in tests | No production changes | More test setup code |
Test Case
def test_unauthorized_endpoint_does_not_log_errors():
"""Verify that unauthorized requests don't spam logs in test mode."""
with auth_app.test_client() as client:
# This should return 401, but not log WARNING/ERROR
response = client.get("/auth/v1/vault")
assert response.status_code == 401
# No WARNING/ERROR should be logged for expected 401s
# (Currently logs WARNING + ERROR stack trace)Priority
Low - Tests pass and the errors are logged, not raised. The main issue is confusing test output and potential masking of real errors.
Labels
bug, integration-tests, flask, test-infrastructure, good-first-issue