How to Mock CLI Output in Typer with unittest.mock
Mock and capture Typer CLI output using unittest.mock.patch and io.StringIO for testing command-line applications.
pip install typer
Python code
25 linesimport typer
from unittest.mock import patch
import io
app = typer.Typer()
@app.command()
def greet(name: str, age: int = 18, uppercase: bool = False):
"""Greet a person with optional formatting."""
message = f"Hello {name}, age {age}"
if uppercase:
message = message.upper()
typer.echo(message)
def main():
# Capture CLI output using mock
test_io = io.StringIO()
with patch("typer.echo", side_effect=test_io.write):
with typer.testing.CliRunner() as runner:
result = runner.invoke(app, ["greet", "Alice", "--age", "30", "--uppercase"])
print(f"Exit code: {result.exit_code}")
print(f"Output: {result.output.strip()}")
if __name__ == "__main__":
main()
Output
Exit code: 0
Output: HELLO ALICE, AGE 30
How it works
The code defines a Typer app with a greet command that takes name, age, and a boolean flag for uppercase output. Using patch("typer.echo", side_effect=test_io.write) replaces Typer's output function with a custom writer that captures text into an in-memory StringIO buffer. The CliRunner from typer.testing provides an isolated test environment for invoking the command with arguments. This approach allows you to inspect result.output and directly test the output without needing a real terminal or subprocess. The side_effect parameter is key — it lets the wrapper call the real StringIO write method instead of returning a substitute value.
Common mistakes
- Forgetting to use `io.StringIO()` before passing it to `side_effect` as `test_io.write`
- Using `patch("typer.echo")` without arguments when you need to capture the output
- Not importing `typer.testing.CliRunner` in the same file as the test code
- Confusing `result.output` (captured stdout) with `sys.stdout` after the runner context exits
Variations
- Use `capsys` fixture from pytest for simpler output capture without explicit patching
- Call `runner.invoke()` with `input=...` instead of passing arguments when testing interactive prompts
Real-world use cases
- Writing unit tests for CLI tools where you need to assert exact command output matches expected text.
- Creating golden-file tests where captured CLI output is compared against stored snapshots in CI.
- Building automated documentation examples that execute a CLI command and embed its real output in generated docs.
Sponsored
More from Modern tooling
- Build a Recipe Runner Mock in Python easy
- Build a Textual TUI App Skeleton in Python easy
- Configure ruff linter rules in pyproject.toml with Python easy
- Data Conversion Helper Functions in Python easy
- How to Bind and Mock structlog Context in Python medium
- How to Build a Chainable Filter Helper in Python easy
Keep learning
Related tutorials and quizzes for this topic.