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

Function Mock Laravel Package

avris/function-mock

Mock PHP functions in unit tests without changing your code. avris/function-mock lets you replace and control built-in and user-defined function calls at runtime, making it easier to test legacy code, edge cases, and hard-to-isolate behavior.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Laravel-Specific Gaps: While Laravel excels at class/method mocking (via PHPUnit/Mockery), this package uniquely addresses global function dependencies (e.g., file_get_contents, date, or custom globals like config()). It aligns with Laravel’s testing philosophy by enabling deterministic, isolated tests without refactoring legacy code.
  • Legacy Code Integration: Ideal for Laravel apps with procedural spaghetti (e.g., old plugins, service containers calling app()->make() directly). The package’s namespace-scoped mocks prevent test pollution in large codebases.
  • Testing Layers:
    • Unit Tests: Mock str_replace in a StringHelper class.
    • Integration Tests: Mock file_get_contents to avoid real HTTP calls.
    • Not for E2E: Avoid mocking in Feature tests where real interactions are needed.

Integration Feasibility

  • Laravel Testing Tools:
    • PHPUnit: Works seamlessly in setUp()/tearDown().
    • Pest: Integrate via beforeEach/afterEach.
    • Laravel Mixins: Not supported, but mocks can be injected via Testing traits.
  • Service Container: No native Laravel integration, but mocks can be initialized in createApplication() for bootstrapped tests.
  • Artisan Commands: Mock global functions in CLI tests (e.g., php artisan test --env=testing).

Technical Risk

Risk Laravel-Specific Impact Mitigation
Namespace Collisions Custom str_replace in app vs. PHP’s str_replace. Use fully qualified names (e.g., \str_replace) or whitelist functions.
Laravel Helpers Mocking app(), config(), or route() fails. Extend the package or use Laravel’s MockApplication instead.
Test Pollution Unmocked functions break subsequent tests. Enforce FunctionMock::unmockAll() in tearDown().
Performance in CI Slow test suites if overused. Benchmark and limit to high-impact functions (e.g., file_get_contents).

Key Questions

  1. Laravel-Specific Use Cases:
    • Should we mock Laravel globals (e.g., app()->make())? If so, this package is insufficient—consider Mockery or Laravel\Testing\TestCase.
    • Are there custom global helpers (e.g., helper('str')) that need mocking? This package won’t work; a wrapper would be needed.
  2. Testing Strategy:
    • Will this replace Laravel’s built-in mocking (e.g., partialMock) or supplement it?
    • How will we handle database-driven global functions (e.g., DB::select())? Use Laravel’s DatabaseMigrations instead.
  3. Long-Term Refactoring:
    • Does this enable incremental modernization (e.g., mocking file_get_contents while migrating to Guzzle)?
    • Will we deprecate global functions post-adoption?
  4. Alternatives:
    • PHPUnit + Reflection: Overkill for simple mocks.
    • Laravel’s MockApplication: Better for container mocking.
    • Custom Solution: Runtime function overriding via runkit (if available).

Integration Approach

Stack Fit

  • Laravel Testing Stack:
    • PHPUnit: Native integration via setUp()/tearDown().
    • Pest: Use beforeEach/afterEach for mock lifecycle.
    • Laravel Dusk: Not recommended (mocking breaks browser interactions).
  • Tooling Synergy:
    • Laravel Mixins: Not supported, but mocks can be preloaded in BootstrapTesting.
    • Laravel Forge/Vapor: Safe for CI/CD (no runtime impact in production).
  • Database Testing:
    • Avoid mocking DB::*: Use Laravel’s DatabaseTransactions or RefreshDatabase instead.

Migration Path

  1. Audit Phase:
    • Run grep -r "file_get_contents\|date\|config(" app/ to identify global function calls.
    • Prioritize functions in critical paths (e.g., API endpoints, CLI commands).
  2. PoC Phase:
    • Mock one function (e.g., file_get_contents) in a FeatureTest.
    • Verify no test pollution in subsequent runs.
  3. Rollout Strategy:
    • Phase 1: Replace flaky Mockery/PHPUnit mocks for globals.
    • Phase 2: Add to team testing templates (e.g., tests/TestCase.php).
    • Phase 3: Document approved functions to mock (e.g., "Never mock dd()").

Compatibility

Laravel Component Compatibility Notes
Service Container No direct integration; mocks must be initialized manually.
Artisan Commands Works in CLI tests (e.g., php artisan test).
Queues/Jobs Mock global functions in Handle classes (e.g., dispatch(new Job())).
Middleware Avoid mocking request()/response()—use Laravel’s HttpTestCase instead.
Events/Listeners Mock global functions in event handlers (e.g., EventServiceProvider).

Sequencing

  1. Initial Setup:
    composer require avris/function-mock --dev
    
    Add to tests/TestCase.php:
    use Avris\FunctionMock\FunctionMock;
    
    protected function tearDown(): void
    {
        FunctionMock::unmockAll();
        parent::tearDown();
    }
    
  2. Test Integration:
    • PHPUnit Example:
      public function test_file_get_contents_mock()
      {
          FunctionMock::mock('file_get_contents', fn() => 'fake-content');
          $result = file_get_contents('https://example.com');
          $this->assertEquals('fake-content', $result);
      }
      
    • Pest Example:
      beforeEach(function () {
          FunctionMock::mock('date', fn() => '2023-01-01');
      });
      
  3. Advanced Use Cases:
    • Mock with Side Effects:
      FunctionMock::mock('log_error', function ($message) {
          $this->fail("Unexpected error: {$message}");
      });
      
    • Assert Mock Calls:
      $mock = FunctionMock::mock('json_encode');
      json_encode(['test' => true]);
      $mock->assertCalled();
      

Operational Impact

Maintenance

  • Pros:
    • Isolated Scope: Mocks are test-environment only; no production impact.
    • Lightweight: Single class (~100 LOC) with no dependencies.
  • Cons:
    • No Laravel Support: Requires manual setup in every test class.
    • Unmaintained Package: Risk of breaking changes (mitigate by forking).
  • Recommendations:
    • Create a Laravel Wrapper:
      namespace App\Testing;
      
      use Avris\FunctionMock\FunctionMock;
      
      class LaravelFunctionMock extends FunctionMock
      {
          public static function mockInContainer(string $function, callable $callback)
          {
              // Add Laravel-specific logic (e.g., container binding)
          }
      }
      
    • Document Approved Functions: Maintain a TESTING_GLOBALS.md file listing safe-to-mock functions.

Support

  • Common Issues:
    • Mock Not Triggering: Check for namespace collisions (e.g., str_replace vs. \str_replace).
    • Test Pollution: Add assertions to verify mocks are unmocked:
      $this->assertFalse(FunctionMock::isMocked('file_get_contents'));
      
    • Performance: Avoid mocking in slow tests (e.g., feature tests with many assertions).
  • Debugging Tips:
    • Use FunctionMock::getMockedFunctions() to list active mocks.
    • Check for static analysis warnings (e.g., PHPStan’s globalFunction rule).

Scaling

  • Performance:
    • Benchmark: Mocking adds <1ms per test (negligible for most suites).
    • CI Impact: Minimal if used for high-value functions (e.g., file_get_contents in unit tests).
  • Large Codebases:
    • Parallel Testing: Works with Pest’s --parallel (no shared state).
    • Monorepos: Share via Composer or Git submodules.
  • Scalability Limits:
    • **Avoid Over-Mock
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.
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
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route