Skip to content

fix(mocktail): clearer error for multi-mock verify closure - #270

Open
realmeylisdev wants to merge 1 commit into
felangel:mainfrom
realmeylisdev:fix/verify-multi-mock-closure-error
Open

fix(mocktail): clearer error for multi-mock verify closure#270
realmeylisdev wants to merge 1 commit into
felangel:mainfrom
realmeylisdev:fix/verify-multi-mock-closure-error

Conversation

@realmeylisdev

Copy link
Copy Markdown

Status

READY

Breaking Changes

NO

Description

When a verify(() { ... }) closure invokes more than one mock member — typically by passing a second mock's getter as an argument to the method being verified — mocktail currently fails with:

Used on a non-mocktail object

That message is only accurate when the closure touched zero mocks. For the multi-invocation case, it's misleading and has led users to believe there's a bug in invocation counting (see #262).

Root cause: the fallback branch in _makeVerify treated _verifyCalls.length != 1 as a single case. Splitting the branch lets us produce a diagnostic that names the actual problem.

This PR:

  • Splits the fallback in _makeVerify to distinguish _verifyCalls.isEmpty (non-mock object) from _verifyCalls.length > 1 (multiple mock invocations inside the closure).
  • Emits a new error message for the multi-invocation case that lists the recorded member names and tells the user to hoist the extra mock accesses into locals before the verify(...) call.
  • Clears _verifyCalls on the failure path so a subsequent verify(...) isn't blocked by the entry-check StateError — this previously required a manual reset() to recover.

Before

verify(() => mockA.doIt(mockB.value)).called(1);
// TestFailure: Used on a non-mocktail object

After

verify(() => mockA.doIt(mockB.value)).called(1);
// TestFailure: verify expects exactly one mock method or getter invocation
// inside the closure, but 2 were recorded: Symbol("value"), Symbol("doIt").
// Capture other mock values into local variables before calling verify(...).

Type of Change

  • 🛠️ Bug fix (non-breaking change which fixes an issue)

Testing

  • New test case verify_test.dart › should fail when closure invokes multiple mock members covers both the new message and the state-cleanup invariant.
  • Full suite: dart test — 221/221 passing.
  • dart analyze — clean.

Related

Refs #262 (does not fully close the issue — the reporter's case is a test-wiring error, not a library bug — but this PR removes the misleading message that contributed to the confusion).

…ck invocations

When a `verify(() { ... })` closure invokes more than one mock member
(e.g. passing another mock's getter as an argument), mocktail previously
failed with "Used on a non-mocktail object" — a message intended for the
no-mock case. Reporters have mistaken this for an invocation-counting bug.

- Split the fallback branch in `_makeVerify` so the message now names
  the invocations that were recorded and points the user at the fix
  (capture values into locals before the verify closure).
- Clear `_verifyCalls` on failure so a subsequent `verify(...)` isn't
  blocked by the stale-state `StateError` in the entry check.
- Add a regression test covering both the new message and the
  state-cleanup invariant.

Refs felangel#262
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