Weave Code
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

Phony Laravel Package

eloquent/phony

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require eloquent/phony-phpunit  # For PHPUnit
    # or
    composer require eloquent/phony-kahlan  # For Kahlan
    
  2. Basic Mock Creation:

    use Eloquent\Phony\Phpunit\Phony; // For PHPUnit
    
    $handle = Phony::mock('App\Services\UserService');
    $mock = $handle->get();
    
  3. Stubbing a Method:

    $handle->findUser->with(1)->returns(['id' => 1, 'name' => 'John']);
    $user = $mock->findUser(1); // Returns ['id' => 1, 'name' => 'John']
    
  4. Verification:

    $handle->findUser->calledWith(1); // Asserts method was called with arg 1
    

First Use Case

Testing a Laravel Controller:

public function testUserProfile()
{
    $handle = Phony::mock('App\Http\Controllers\UserController');
    $controller = $handle->get();

    $handle->getUser->with(1)->returns(['name' => 'John']);

    $response = $controller->profile(1);
    $this->assertEquals('John', $response['name']);
    $handle->getUser->calledWith(1);
}

Implementation Patterns

Common Workflows

  1. Dependency Injection Mocking:

    // In a Laravel service provider
    $this->app->bind('App\Services\PaymentGateway', function () {
        $handle = Phony::mock('App\Services\PaymentGateway');
        $handle->charge->with(100)->returns(true);
        return $handle->get();
    });
    
  2. Stubbing Database Interactions:

    $handle = Phony::mock('App\Models\User');
    $handle->find->with(1)->returns(new User(['name' => 'John']));
    $user = User::find(1); // Returns mocked user
    
  3. Spying on External API Calls:

    $handle = Phony::mock('GuzzleHttp\Client');
    $handle->get->with('https://api.example.com/data')->returns(['data' => 'test']);
    
    $client = $handle->get();
    $response = $client->get('https://api.example.com/data');
    $handle->get->calledWith('https://api.example.com/data');
    
  4. Testing Middleware:

    $handle = Phony::mock('App\Http\Middleware\Authenticate');
    $middleware = $handle->get();
    
    $handle->handle->with($request, $next)->returns($response);
    

Integration Tips

  • Laravel Service Container: Use Phony::mock() in setUp() to mock dependencies before each test.

    public function setUp(): void
    {
        parent::setUp();
        $this->mock = Phony::mock('App\Services\SomeService');
        $this->app->instance('App\Services\SomeService', $this->mock->get());
    }
    
  • Trait Mocking:

    $handle = Phony::mock('App\Traits\Loggable');
    $trait = $handle->get();
    $handle->log->with('message')->returns(true);
    
  • Static Method Stubbing:

    $handle = Phony::mock('App\Helpers\StringHelper');
    $handle->staticMethod->returns('static result');
    
  • Exception Stubbing:

    $handle->method->throws(new \RuntimeException('Error'));
    
  • Generator Stubbing:

    $handle->getItems->returns(function () {
        yield 'item1';
        yield 'item2';
    });
    

Gotchas and Tips

Pitfalls

  1. Archived Package:

    • Phony is no longer maintained. Use alternatives like mockery/mockery or phpunit/phpunit for new projects.
    • If stuck with legacy code, ensure tests are isolated to avoid breaking changes.
  2. Reference Arguments:

    • Phony supports reference arguments, but ensure your stubs handle them explicitly:
      $handle->method->withArgs([&$arg])->returns(true);
      
  3. Final Classes:

    • Use proxy mocks for final classes:
      $handle = Phony::mock('App\Services\FinalService', true); // Enable proxy
      
  4. Order Verification:

    • Phony supports order verification, but ensure tests are written to expect calls in a specific sequence:
      $handle->method1->called();
      $handle->method2->called();
      $handle->verifyOrder();
      
  5. Hamcrest Matchers:

    • Some matchers may not work as expected. Stick to basic assertions for reliability.

Debugging Tips

  • Detailed Verification Output: Phony provides verbose output for failed assertions. Use this to pinpoint issues:

    $handle->method->calledWith('expected'); // Fails with detailed diff
    
  • Stubbing vs. Spying:

    • Stubbing replaces behavior; spying verifies calls without altering behavior.
    • Mixing both can lead to confusing tests. Prefer one style per test.
  • Partial Mocks:

    • Use Phony::partialMock() to mock only specific methods of a class:
      $handle = Phony::partialMock('App\Models\User', ['find']);
      
  • Custom Class Names:

    • Override class names for clarity in tests:
      $handle = Phony::mock('App\Models\User', 'MockedUser');
      

Extension Points

  1. Custom Matchers:

    • Extend Phony’s matcher system for domain-specific assertions:
      $handle->method->calledWith($this->customMatcher());
      
  2. Mock Builders:

    • Create reusable mock configurations:
      $builder = Phony::mockBuilder('App\Services\PaymentGateway')
          ->method('charge')->returns(true);
      $handle = $builder->mock();
      
  3. Integration with Laravel:

    • Override Laravel’s createApplication() to inject mocks:
      protected function createApplication()
      {
          $app = require __DIR__.'/../../bootstrap/app.php';
          $app->bind('App\Services\SomeService', function () {
              return Phony::mock('App\Services\SomeService')->get();
          });
          return $app;
      }
      
  4. Generator Verification:

    • Verify generator output step-by-step:
      $handle->getItems->returns(function () {
          yield 'item1';
          yield 'item2';
      });
      $items = iterator_to_array($handle->getItems());
      $this->assertEquals(['item1', 'item2'], $items);
      
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.
aimeos/prisma
besmartand-pro/php-quality-config
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor
spatie/laravel-javascript-views