Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Mockdoctrinemanager Laravel Package

yosimitso/mockdoctrinemanager

A lightweight testing helper that mocks the Doctrine manager so you can unit test persistence-dependent code without a real database. Swap in the mock to stub repository lookups, flush and transaction calls, keeping tests fast and isolated.

View on GitHub
Deep Wiki
Context7

Getting Started

V1.0 is a new, deliberately narrow package: it records the entity-manager operations that matter in tests — persist, flush, remove, and the transaction lifecycle (beginTransaction, commit, rollback). It is not a full EntityManager replacement; it is an assertion surface for code that manipulates Doctrine-style persistence.

First steps:

  1. Require it as a dev dependency (composer require --dev <vendor>/<package>) so it never ships to production.
  2. Open the package source and locate the class exposing the listed methods. The release notes define the API but not the concrete class name or service binding, so confirm that first.
  3. Register or resolve that recorder in a test. In Laravel, check whether it is auto-discovered; otherwise bind it manually in the test or a base TestCase.
  4. Exercise the code under test — a controller action, job, service, or repository — then assert against the recorder.

A good first use case is a feature test that posts to an endpoint creating an entity, then verifies both persistence and transaction behaviour:

$recorder = app(EntityManagerRecorder::class); // confirm actual class/binding

$this->post('/orders', $payload)->assertCreated();

$order = $recorder->getPersistedEntity(Order::class);

$this->assertInstanceOf(Order::class, $order);
$this->assertTrue($recorder->hasBegunTransaction());
$this->assertTrue($recorder->hasComitted());

Start with the simplest assertion — “was this entity persisted?” — before layering on flush and transaction checks.

Implementation Patterns

Arrange / Act / Assert around the recorder. Resolve the recorder before invoking the code under test, perform the action, then inspect the recorded state. This keeps assertions about side effects out of the production code.

Swap the binding in feature tests. If your application type-hints an EntityManager or a repository that depends on one, bind the recorder in the container for that test. This lets unchanged application code run while the recorder captures calls.

Use positional lookup for repeated entities. getPersistedEntity(Order::class, 1) returns the first persisted Order, position 2 the second, and so on. This is useful for bulk-import or batch-create tests where several entities of the same class are handled in one request.

$first  = $recorder->getPersistedEntity(Order::class, 1);
$second = $recorder->getPersistedEntity(Order::class, 2);

$this->assertSame('A-100', $first->reference);
$this->assertSame('A-101', $second->reference);

Assert persist and flush separately. persist() and flush() are recorded independently. A service that persists but forgets to flush will still produce a persisted entity. Use getFlushedEntities() or getFlushedEntity() to confirm the unit of work was actually committed to the database layer.

Model transaction workflows explicitly. For write services, assert the expected lifecycle:

$this->assertTrue($recorder->hasBegunTransaction());
$this->assertTrue($recorder->hasComitted());
$this->assertFalse($recorder->hasRolledback());

For failure-path tests, trigger the exception and assert hasRolledback() instead. This is the most valuable use of the package: proving rollback behaviour without needing a real database failure.

Pair remove with persist checks. When testing delete flows, assert both the removal and the absence of the entity from the persisted list:

$this->assertInstanceOf(Order::class, $recorder->getRemovedEntity(Order::class));
$this->assertEmpty($recorder->getPersistedEntities());

Use array getters for collection-level assertions. getPersistedEntities() and getFlushedEntities() are better than looping singular getters when asserting counts, ordering, or the complete set of affected classes.

Keep the recorder test-scoped. Bind it as a fresh instance per test (for example via app()->instance() inside each test or a scoped binding). Do not rely on a singleton accumulating calls across tests.

Gotchas and Tips

  • hasComitted() is misspelled in the public API. It is spelled with one t in “Comitted”. Use the exact method name; a future release may correct or alias it, which would be a breaking change for existing tests. Centralise calls in a helper if you want to insulate your suite.
  • Position is 1-based. getPersistedEntity(Foo::class) defaults to position 1, not 0. Off-by-one errors here produce confusing “wrong entity” assertions.
  • The signature says object $className but the name implies a class-string. Verify whether the first argument expects Order::class or an object instance. If it truly requires an object, passing a class-string will fail. This is an API/documentation inconsistency worth checking against the source before writing many tests.
  • Return type is mixed. Getters may return null when nothing matches. Assert assertNotNull() or assertInstanceOf() before accessing properties, otherwise a missing record becomes a null-property error far from the real failure.
  • There is no plural getRemovedEntities(). Only getRemovedEntity() is exposed. To assert multiple removals, call it by position or wrap it in your own helper.
  • Transaction booleans are independent flags, not a state machine. hasBegunTransaction() can remain true after a commit or rollback. Do not assume the three booleans are mutually exclusive; assert the combinations you expect explicitly.
  • Nested transactions are not covered. Only the operations listed in V1.0 are recorded. Savepoints and nested transaction behaviour should be tested elsewhere.
  • Only listed operations are recorded. Any other EntityManager method used by your code will not appear in these assertions. This is an extension point: subclass or decorate the recorder, or wrap it in a test helper, rather than assuming full coverage.
  • Watch for state leakage. If the recorder is bound as a singleton, assertions in later tests can see calls from earlier ones. Resolve fresh per test and avoid sharing it across test methods.
  • Debug by dumping the arrays. When an assertion unexpectedly fails, dump($recorder->getPersistedEntities(), $recorder->getFlushedEntities()) quickly shows what was and was not recorded. This is faster than stepping through the production code.
  • Do not treat this as a database test. It verifies that persistence calls were made, not that rows exist. Keep a smaller number of real integration tests for actual database constraints, cascades, and query behaviour.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect