brain/monkey
Brain Monkey is a PHP testing library for mocking and spying on global functions and class methods, with seamless PHPUnit integration and no dependencies—ideal for testing legacy code, WordPress plugins, and function-heavy PHP applications.
add_action, add_filter, get_option, wp_remote_*, wp_enqueue_*, and shortcodes without booting WordPress. That gives you a real pass/fail signal on new features before integration or QA time is spent, which shortens the decision loop on scope and acceptance. Release 2.7.0 extends this to has_filter() / has_action() with the $priority argument added in WordPress 6.9, so hook-priority assertions — "did we register at priority 20 so we run after WooCommerce?" — are now a first-class unit test rather than an integration-only concern.$priority support and the alignment of mock defaults with WP Core (doing_action, doing_filter, do_action_deprecated, apply_filters_deprecated, has_filter, has_action) mean fewer mock-vs-core divergences as we track WP releases. Mocks that drift from core behavior are silent false passes; each release that closes a gap is a direct reduction in that risk.WP_Error), and remote-call failure branches; a small integration suite covers real DB, REST, and rendering behavior.Adopt when:
add_action was registered with the right hook, callback, priority, and arg count; that wp_enqueue_script got the right handle and version; that a filter returns the expected shape — and, as of 2.7.0, that has_filter() / has_action() return correctly for a given $priority.WP_Error returns, missing options — which are painful to trigger against a real WordPress instance.Look elsewhere, or supplement, when:
wp-phpunit) or WP-CLI-based acceptance tests instead.add_action was called exactly once") and create false confidence. Fund the practice, not just the package.For executives: Brain Monkey is a free, MIT-licensed, development-only testing utility for our WordPress plugin. It has zero production footprint — it is not shipped, adds no weight to the plugin, and introduces no runtime or security surface for customers. It lets engineers verify plugin behavior in seconds without standing up a WordPress site, which means faster releases, fewer regressions reaching customers, and cheaper CI. The just-released 2.7.0 is a routine, non-breaking maintenance update: it adds support for a new WordPress 6.9 capability, confirms compatibility with PHP 8.4 and 8.5, and ships a leaner package. That is exactly the upkeep we would otherwise fund internally. It remains a small, reversible, low-cost bet that de-risks the larger roadmap items we already committed to — PHP upgrades, platform compatibility, and refactoring hook-heavy code. Ask: approve as a dev dependency with a pinned version and a defined owner; approve the 2.7.0 bump as a routine low-risk upgrade.
For engineering: It is the de facto standard for unit-testing WordPress plugins. It layers on PHPUnit and Mockery and gives you Functions\when() / expect(), plus helpers for actions, filters, and shortcodes, so you can assert that a hook was registered correctly or that an HTTP failure path returns the right WP_Error. What changed in 2.7.0 and what to do about it: has_filter() / has_action() mocks now accept $priority (WP 6.9) — add priority assertions where ordering matters; several mock defaults were aligned with WP Core, so re-run the suite on the bump and treat any failures as tests that were encoding the old mock's behavior rather than real behavior; Mockery constraints are tighter, so verify the resolved version; and dev-only files are no longer in the distributed package. Constraints to plan around: it redefines functions at runtime via a stream wrapper, so validate against our PHP and opcache matrix first (PHP 8.4/8.5 are now confirmed upstream); it does not mock classes, so Mockery still does that work; and it says nothing about real WordPress behavior, so we keep a small integration suite for DB, REST, and rendering. Mitigations: pin the version, wrap setup/teardown in a shared base test case so a future swap is a one-file change, and enforce assertion style in review so tests describe intent rather than implementation. Success looks like: WP-facing unit coverage up, suite runtime under a minute, defect escape rate down, and no increase in integration-test flakiness.
How can I help you explore Laravel packages today?