responses icon indicating copy to clipboard operation
responses copied to clipboard

Make `assert_all_requests_are_fired` always assert on exception

Open RJPercival opened this issue 2 months ago • 1 comments

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_exception parameter - 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 tox and pre-commit checks 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

RJPercival avatar Nov 03 '25 10:11 RJPercival

Hi @markstory, is there anything else you'd like updated on the PR, or are you now happy to approve it?

RJPercival avatar Nov 24 '25 12:11 RJPercival