Skip to content

preserve(#7264): feat(tests): canonical make_async_redis() + patch_async_redis() fixtures (#7264) - #8000

Closed
mrveiss wants to merge 1 commit into
Dev_new_guifrom
issue-7264
Closed

mrveiss wants to merge 1 commit into
Dev_new_guifrom
issue-7264

Conversation

@mrveiss

@mrveiss mrveiss commented May 17, 2026

Copy link
Copy Markdown
Owner

Preservation PR — issue #7264 is closed but work was never submitted. Branch: issue-7264, 1 commit(s). Created by MVA-588 worktree audit.

…res (#7264)

Composability follow-up to #7216 (PR #7234) and #7134 (PR #7139). After
the async-mock pattern fix consolidated 77 sites onto
``patch(..., new=AsyncMock(return_value=mock_redis))``, 11+ test files
still rolled their own ``_make_redis*()`` fixture with slightly
different defaults each. This PR extracts the canonical shape.

What lands
----------
``tests/fixtures/mocks.py`` adds:

  make_async_redis(*, get_returns=None, set_returns=True, ...,
                   **extra_methods) -> AsyncMock
      Build a redis-shaped AsyncMock with sensible defaults for the top
      ~30 redis methods used in this codebase (per a grep over all
      *test*.py files: get×170, hgetall×47, set×46, hset×33, expire×29,
      delete×29, ...). Per-method override via ``X_returns=`` kwargs.
      Less common methods (e.g. xadd for streams) via ``**extra_methods``
      kwargs — each becomes ``AsyncMock(return_value=value)``.

  @contextmanager patch_async_redis(target, redis=None)
      Context manager that wraps ``patch(target, new=AsyncMock(return_
      value=redis))`` and yields the inner redis mock for configuration.
      Eliminates the #7216 footgun: bare ``patch(target,
      return_value=mock)`` returns the default AsyncMock when the
      production code awaits ``get_async_redis_client(...)``, NOT the
      mock the caller wanted.

Re-exported from ``tests/fixtures/__init__.py`` (matches #7134 precedent).

Sensible defaults (the empty/healthy shape callers usually want)
----------------------------------------------------------------
  - get / hget / hgetall / keys / smembers / lrange / zrange → empty/None
  - set / setex / expire → True
  - sadd / srem / zadd / lpush / rpush / incr / hset / delete → 1
  - sismember / hexists / exists → 0 / False

Bug caught during implementation
--------------------------------
First version of ``patch_async_redis`` returned ``patch(target, new=...)``
directly — but ``with patch(...) as X: X`` yields the patched ``new``
object, NOT the inner ``redis`` mock the caller needs to configure. So
``with patch_async_redis(target) as redis: redis.get = AsyncMock(...)``
was setting attributes on the wrong object — production saw the default
None from the un-overridden inner mock.

Caught by my own contract test ``test_patch_async_redis_basic_use`` —
asserted production receives the configured value, got None. Fixed by
making ``patch_async_redis`` a ``@contextmanager`` that explicitly
yields the inner redis mock. The contract test became the regression
pin: any future rewrite of the helper that drops the contextmanager
form will fail this test.

Verification
------------
  $ python3 -m pytest tests/fixtures/test_make_async_redis.py -xvs
  ============================== 17 passed in 1.25s ==============================

Migration follow-up
-------------------
This PR adds the fixture + tests + documentation. The 11+ ad-hoc
``_make_redis*()`` helpers across the test tree migrate incrementally
in separate PRs (per the layered-rot lesson — each migration may
surface its own pre-existing rot).

Closes #7264

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mrveiss

mrveiss commented May 17, 2026

Copy link
Copy Markdown
Owner Author

Closing: this preserve branch has critical CI failures that prevent safe merging. The work-in-progress state has been preserved in the branch. The failures should be fixed before this work is re-submitted.

@mrveiss mrveiss closed this May 17, 2026
@github-actions
github-actions Bot deleted the issue-7264 branch May 18, 2026 06:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant