Make `assert_all_requests_are_fired` always assert on exception
What type of PR is this? (check all applicable)
- [ ] Refactor
- [ ] Feature
- [x] Bug Fix
- [ ] Optimization
- [ ] Documentation Update
- [ ] Other
Description
This PR modifies the behavior of assert_all_requests_are_fired to always raise assertions about unfired requests, even when an exception occurs in the context manager or decorated function. This is a breaking change that improves debugging capabilities by providing complete context about both the original failure and the state of mocked requests.
Background
Previously, when a test failed within the scope of RequestsMock (e.g. an exception was raised or an assertion failed), responses would skip asserting that all requests were fired to avoid masking the original exception. This could hide useful debugging information, as the test failure may have been a side effect of an expected request not being called (e.g. the mocked URL was wrong).
An earlier iteration of this PR introduced an assert_on_exception parameter to make this behavior configurable. However, after further consideration, the new behavior is so valuable for debugging that it should be the default and only behavior.
Key Changes
-
Breaking Change: When
assert_all_requests_are_fired=True, assertions about unfired requests are now always raised, even when an exception occurs - Exception Chaining: The original exception is preserved as context, so developers see both the original error and which requests weren't called
-
Simplified API: Removed the
assert_on_exceptionparameter - the improved behavior is now automatic - Enhanced Debugging: Developers always get complete information about mocked request state during failures
Exception Handling Example
Before (old behavior):
with responses.RequestsMock(assert_all_requests_are_fired=True) as rsps:
rsps.add(responses.GET, "http://example.com/users", body="test")
rsps.add(responses.GET, "http://example.com/profile", body="test") # Not called
requests.get("http://example.com/users")
raise ValueError("Something went wrong")
# Output: Only shows ValueError, unfired request info is lost
# ValueError: Something went wrong
After (new behavior):
with responses.RequestsMock(assert_all_requests_are_fired=True) as rsps:
rsps.add(responses.GET, "http://example.com/users", body="test")
rsps.add(responses.GET, "http://example.com/profile", body="test") # Not called
requests.get("http://example.com/users")
raise ValueError("Something went wrong")
# Output: Shows both exceptions with proper chaining
# ValueError: Something went wrong
#
# During handling of the above exception, another exception occurred:
#
# AssertionError: Not all requests have been executed [('GET', 'http://example.com/profile')]
Benefits
- Complete Debug Context: Always see both the original error and unfired request information
- Exception Chaining: Python's built-in exception chaining preserves full error context
- Simplified API: No additional parameters needed - the behavior "just works"
- Better Test Reliability: Failures provide maximum debugging information
[!IMPORTANT] This is a breaking change. Code that previously relied on unfired request assertions being suppressed during exceptions will now see those assertions raised. However, this change improves debugging capabilities significantly.
Related Issues
- #72 (this PR refines the fix for that issue by benefiting from exception chaining)
PR checklist
Before submitting this pull request, I have done the following:
- [x] Read the contributing guidelines
- [x] Ran
toxandpre-commitchecks locally - [x] Added my changes to the CHANGES file
Added/updated tests?
Current repository has 100% test coverage.
- [x] Yes
- [ ] No, and this is why:
- [ ] I need help with writing tests
Test Coverage: Comprehensive tests updated to verify:
- Context manager behavior with assertions raised during exceptions
- Decorator functionality with new behavior
- Exception chaining verification
- Documentation examples work as expected
Hi @markstory, is there anything else you'd like updated on the PR, or are you now happy to approve it?