Skip to content

A later catch-all stub silently makes an earlier specific stub unreachable #136

Closed

Description

@rasuvaeff
when(fn () => $r->find(1))->returns(new Book('one'));
when(fn () => $r->find(Arg::any()))->returns(null);
$r->find(1);   // null

"Most recently registered wins, earlier ones remain as fallbacks" is documented, and the README says to register the broad stub first — but the opposite order is not diagnosed: the specific stub stays registered, matches nothing, and even strictStubs does not report it, because unreachable is not the same as uncalled. The library's stated promise is that nothing happens silently.

Expected: registering a stub whose every position accepts anything (Arg::any(), unspelled, Arg::rest()) after another stub of the same method is refused with ConflictingExpectation, naming the specification it would shadow.

Found in the 2026-09-18 family review.

Activity

  1. self-assigned this
    on Sep 17, 2026
  2. rasuvaeff commented on Sep 17, 2026

    @rasuvaeff
    OwnerAuthor

    Closed as documented rather than changed: the engine's own property model (DispatchIndexPropertyTest, EnginePropertyTest) treats "later wins" as law, and refusing a catch-all after a specific stub broke three of them. README EN/RU and llms.txt now say it plainly in #139: register the broad stub first; a catch-all after a specific one is not diagnosed, and strictStubs stays quiet because unreachable is not uncalled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions