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

Laravel Database Mock Laravel Package

mpyw/laravel-database-mock

Experimental Laravel package that mocks underlying PDO connections with Mockery, letting you stub SELECT, INSERT, and UPDATE queries and results for fast, database-free tests. Requires PHP 8.2+ and Laravel 11+.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This package intercepts at the lowest useful seam in the Laravel stack: it swaps the PDO handle beneath Laravel's Connection classes for a Mockery double, leaving the query builder, Eloquent hydration, casts, accessors, timestamp handling, and collections running for real. For a TPM the significance is that tests written against it still exercise application logic while faking only the network boundary — a materially stronger proposition than stubbing models or repositories, which mock away the code you actually want to verify. The standout capability is mockEachPdo() with reader()/writer(): read/write replica misrouting is a genuine production bug class that single-database SQLite tests structurally cannot catch, and this is the cheapest credible way to assert routing intent without provisioning topology. Requirements are explicit and modern — PHP ^8.2, Laravel ^11 || ^12 || ^13 || ^14, Mockery already present — and there is no service provider, config file, or publish step, keeping the integration surface gratifyingly small.

Integration feasibility. Technically trivial: one dev dependency, one composer require, one DBMock::mockPdo() call at the top of a test body. The friction is not installation but adoption shape. The mock is expectation-based, ordered, and strict — every query the code under test issues must be declared in sequence — so existing tests are not retrofittable; each one must be re-scripted against the exact SQL Laravel generates. Budget the effort as test authoring, not as a dependency bump. Realistically this is a one-to-two-day spike plus a half-day-per-test-class conversion for whoever owns the pilot.

Technical risk. Elevated and worth stating plainly to stakeholders. Version is v0.0.1-alpha7; the package is self-labelled experimental; it carries a second alpha dependency (mpyw/mockery-pdo) that owns most of the expressive API; it has 6 stars, 0 dependents, and a single maintainer. That is a bus-factor of one for a library that would sit on your critical test path. Compounding this, the assertions bind to generated SQL text — a Laravel grammar tweak or a query-builder refactor breaks tests silently at the string level, which reads to the team as flakiness rather than as an upgrade obligation. Mitigations are cheap and non-negotiable: pin the exact alpha and commit the lockfile, confine usage to a dedicated tests/SqlContract/ directory rather than the base test case, wrap DBMock in your own thin helper so a future API shift is a one-file change, and run those tests in CI on both the oldest and newest supported Laravel versions.

Key questions. Does our suite actually configure separate read/write hosts, or would mockEachPdo() be speculative capability? Which driver grammar do our tests use — the README's backticked SQL assumes MySQL, and SQLite/Postgres quoting will fail every assertion, so the mocked strings must match the configured test connection. How many of our critical paths are transaction-heavy, given DB::transaction() issues real beginTransaction/commit/rollBack calls that must be scripted? Who owns this tier — a named maintainer, or will it rot the first time Laravel bumps a grammar? And what is our exit ramp if the maintainer stops publishing: the wrapper helper plus a small, quarantined surface is the answer, and it only holds if we enforce it from day one.

Verdict. Worth a bounded pilot for teams whose database-layer risk is concentrated in replica routing or in verifying SQL shape for reporting/billing queries. Not worth it as a general test strategy — the strictness and snapshot tax scale badly, and the alpha status makes it unsuitable for anything an organisation cannot afford to rip out.

Integration Approach

Stack fit. The package slots in cleanly beside an existing PHPUnit or Pest suite; the API is Mockery-shaped, so it reads naturally where Mockery is already in use and awkwardly next to Laravel's fake()/expect() helpers — keep it in its own directory and don't mix styles within a file. The important compatibility axis is not the framework version but the database driver: assertions are written against generated SQL text plus positional bindings, so the test connection's grammar determines every string you write. Decide the driver before writing test one, and document it next to the directory.

Migration path. Do not touch a base test case, a setUp(), or a CI step until a spike has proven value. The sequence that works: prove one query shape in one test class, then formalise a small "SQL contract" tier for repositories, reporting/billing query builders, replica routing, and connection-failure paths, while leaving RefreshDatabase/in-memory SQLite as the default for everything else. This is additive, not a replacement — treat it as a second tier with an explicitly documented boundary, not as a migration target.

Compatibility. Four things bite in practice and should be in the onboarding note: identifiers quote differently per driver (`users` vs "users"); bindings are positional and exact, so booleans, decimals, enums, and datetimes must match the driver's parameter form; lastInsertId() is a separate Mockery expectation that must be declared or inserts silently produce null IDs; and Mockery::close() must be in tearDown(), because unmet expectations surface there with a message that never mentions this package. Carbon::setTestNow() is effectively mandatory on every write path, since timestamps are baked into both the SQL bindings and the hydrated attributes.

Sequencing. (1) Confirm PHP/Laravel/Mockery versions and which driver the test connection uses. (2) composer require mpyw/laravel-database-mock:VERSION@alpha --dev, pin exact, commit lockfile. (3) Spike one test class against a single repository or query object; verify Eloquent hydration assertions (->toArray()) pass alongside SQL assertions. (4) Build the DBMock wrapper helper and the tests/SqlContract/ convention with a short README. (5) Add the CI matrix leg on oldest and newest supported Laravel. (6) Gate wider adoption on the pilot surviving one Laravel patch upgrade without unexplained failures — that is the real test of ongoing cost.

Operational Impact

Maintenance. The recurring cost is snapshot maintenance, and it is the single largest line item. Every mocked SQL string is an assertion the team owns; a query-builder refactor, an added exists(), a new eager-load, or a driver grammar tweak breaks it. Two alpha dependencies must be tracked and upgraded together, and each Laravel major bump should trigger a deliberate re-verification of the whole tier rather than an incidental fix. The wrapper helper is the primary cost-control device — it centralises the blast radius of an API change in one file.

Support. There is no vendor, no SLA, and effectively no community: one maintainer, six stars, zero dependents. Assume self-support and plan accordingly — whoever adopts this must be able to read mpyw/mockery-pdo's source when the README runs out, and should expect to vendor or fork if the project stalls. Do not let this library become a single-person dependency in an otherwise well-supported test stack without a named owner and a documented abandonment plan.

Scaling. Cost scales linearly and unfavourably with test count: each additional mocked test is a new hand-written SQL contract. The tier should therefore stay deliberately small and high-value — replica routing, connection-failure and retry branches, and SQL shape for the handful of queries where correctness is expensive to get wrong. It should not absorb general CRUD coverage, where RefreshDatabase plus SQLite delivers more behaviour for less maintenance. The runtime benefit (no database round-trip) is real but only materialises as a test-suite speed win at a surface small enough that the benefit is modest; position this as a fidelity tool, not a performance one.

Failure modes. Expect: unmet expectations firing in teardown with messages that don't name the package; driver-grammar mismatches producing wall-to-wall failures on first run; missing lastInsertId() stubs surfacing as confusing model-assertion failures far from the cause; statelessness surprises, where the mock does not remember what you "wrote" and multi-step flows need a shouldSelect returning the row you just inserted; and transaction tests that need beginTransaction/commit/rollBack scripted explicitly, with rollback-on-exception needing extra care. The most dangerous failure mode is quieter — false confidence. There are no triggers, foreign-key cascades, unique constraints, generated columns, collation rules, or real isolation here; this tier verifies calls, not database behaviour, and must never be allowed to displace integration coverage. A team that forgets this will ship a green build over an untested constraint.

Ramp-up. The API is small and the README's examples cover the mental model in about ten lines, so a mid-level developer can be productive in an afternoon. The hidden cost is the prerequisite knowledge: contributors must be able to reason about the exact SQL and exact bindings Laravel emits, which is a step above typical feature-test fluency. Budget for that, and make the boundary explicit in the tier's README — what it covers, what it deliberately does not, and where integration tests still own the truth. Documenting the non-goals is worth more than documenting the API.

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.
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode