How to Avoid SELECT * and Mock SQL Column Queries in Python
Mock a SQLite cursor to verify that queries specify explicit columns instead of using SELECT *.
Python code
26 linesimport sqlite3
from unittest.mock import Mock, patch
def get_user_emails(connection):
"""Fetch only the required columns instead of SELECT *."""
cursor = connection.cursor()
cursor.execute("SELECT email FROM users")
return [row[0] for row in cursor.fetchall()]
def test_get_user_emails_specific_columns():
mock_connection = Mock()
mock_cursor = mock_connection.cursor.return_value
mock_cursor.fetchall.return_value = [("alice@example.com",), ("bob@example.com",)]
emails = get_user_emails(mock_connection)
# Verify the exact SQL with explicit column names
mock_cursor.execute.assert_called_with("SELECT email FROM users")
assert emails == ["alice@example.com", "bob@example.com"]
if __name__ == "__main__":
test_get_user_emails_specific_columns()
print("All tests passed - query explicitly specifies columns, avoiding SELECT *")
Output
All tests passed - query explicitly specifies columns, avoiding SELECT *
How it works
The test creates a Mock connection and cursor to simulate a database without a real connection. The cursor.execute call is asserted to have the exact SQL string 'SELECT email FROM users', enforcing explicit column selection. The fetchall return value is a list of tuples, each containing a single email, matching the row[0] extraction. This pattern ensures your code avoids SELECT * which can hurt performance and maintainability. Using mocks isolates the query logic from actual database dependencies, making tests fast and reliable.
Common mistakes
- Forgetting to set `mock_cursor.fetchall.return_value` before calling the function.
- Using `SELECT *` in the query, defeating the purpose of the test.
- Not asserting the exact SQL string, allowing silent regression to star selects.
Variations
- Use `pytest` with `monkeypatch` to replace `connection.cursor` for integration tests.
- Use `moto` or a real test database to verify column selection end-to-end.
Real-world use cases
- Enforcing query best practices in a code review pipeline to prevent inefficient full-table scans.
- Unit testing data access functions without spinning up a real database in CI.
- Refactoring legacy SQL to explicit columns to mitigate schema change breakages.
Sponsored
More from Database scaling & optimization
- Approximate Count with HyperLogLog in Python medium
- B-Tree Insert and In-Order Traversal in Python hard
- Broadcast a Small Reference Table in Python easy
- Build a Full Text Search Index in Python medium
- Build a Partial Index Mock in Python for Database Filtering easy
- Composite index leftmost prefix in Python medium
Keep learning
Related tutorials and quizzes for this topic.