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

Hamcrest Php Laravel Package

hamcrest/hamcrest-php

Official PHP port of Hamcrest matchers for expressive assertions in tests. Use MatcherAssert::assertThat() or convenient global functions (assertThat, equalTo, is, both/andAlso, either/orElse) to build readable, composable matchers with PHP-friendly typing.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:
    composer require hamcrest/hamcrest-php
    
  2. Enable Global Functions (required for assertThat sugar):
    use Hamcrest\Util;
    Util::registerGlobalFunctions();
    
  3. First Assertion (in a test file):
    assertThat('foo', equalTo('foo'));
    

First Use Case: Validating API Responses

$response = $this->get('/api/users/1');
$expected = [
    'id' => 1,
    'name' => 'John Doe',
    'email' => 'john@example.com'
];

assertThat(json_decode($response->getContent(), true),
    arrayContaining([
        'id' => equalTo(1),
        'name' => equalToIgnoringCase('john doe'),
        'email' => matchesPattern('/^[^\s@]+@[^\s@]+\.[^\s@]+$/')
    ])
);

Where to Look First:


Implementation Patterns

1. Composable Assertions

Workflow: Break complex validations into reusable matchers.

// Reusable matcher for valid email
$validEmail = matchesPattern('/^[^\s@]+@[^\s@]+\.[^\s@]+$/');

// Usage
assertThat($user['email'], $validEmail);
assertThat($users, everyItem(hasKey('email', $validEmail)));

2. Fluent Chaining

Pattern: Combine matchers for nested validations.

assertThat($order,
    allOf(
        hasKey('items', arrayWithSize(greaterThan(0))),
        hasKey('total', greaterThanOrEqualTo(100)),
        hasKey('status', equalTo('completed'))
    )
);

3. Custom Matchers

Extension Point: Create domain-specific matchers.

use Hamcrest\Matcher;

class ValidSlug extends Matcher {
    public function matches($slug) {
        return preg_match('/^[a-z0-9-]+$/', $slug);
    }
    public function describeTo($description) {
        $description->appendText('a valid slug (alphanumeric and hyphens)');
    }
}

// Usage
assertThat($post['slug'], new ValidSlug());

4. Integration with PHPUnit

Tip: Use MatcherAssert for programmatic assertions.

use Hamcrest\MatcherAssert;

public function testUserValidation() {
    $user = ['name' => 'Alice', 'age' => 30];
    MatcherAssert::assertThat(
        $user,
        allOf(
            hasKey('name', notEmptyString()),
            hasKey('age', integerValue())
        )
    );
}

5. Data-Driven Tests

Pattern: Parameterize matchers for test suites.

$data = [
    ['input' => 'foo', 'expected' => 'FOO'],
    ['input' => 'bar', 'expected' => 'BAR'],
];

foreach ($data as $test) {
    assertThat(
        strtoupper($test['input']),
        equalTo($test['expected'])
    );
}

6. Exception Handling

Use Case: Validate exceptions with Hamcrest.

$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessageThat(
    containsString('Invalid input')
);

Gotchas and Tips

Pitfalls

  1. Global Functions Not Auto-Loaded

    • Issue: assertThat() fails with undefined function unless Util::registerGlobalFunctions() is called.
    • Fix: Add to bootstrap.php or test base class:
      Util::registerGlobalFunctions();
      
  2. Case Sensitivity in equalTo

    • Gotcha: equalTo('foo') fails for 'Foo' (use equalToIgnoringCase).
    • Tip: Prefer equalToIgnoringCase for user-generated strings.
  3. Array Order Sensitivity

    • Issue: arrayContaining([1, 2]) fails for [2, 1] (use arrayContainingInAnyOrder).
    • Fix: Use containsInAnyOrder for unordered collections.
  4. Null Handling Quirks

    • Gotcha: nullValue() matches null, but notNullValue() fails for 0, false, or ''.
    • Tip: Use is(notNullValue()) explicitly.
  5. PHP 8+ Type Safety

    • Issue: PHP 8.4’s implicit nullability may cause matcher failures.
    • Fix: Explicitly declare return types in custom matchers:
      public function matches(mixed $value): bool { ... }
      
  6. Double Inclusion Warnings

    • Gotcha: Loading global functions twice triggers warnings.
    • Fix: Guard with:
      if (!function_exists('assertThat')) {
          Util::registerGlobalFunctions();
      }
      

Debugging Tips

  1. Descriptive Failures

    • Use describedAs() to customize error messages:
      assertThat($user['email'], describedAs('valid email', $validEmail));
      
  2. MatcherAssert Count

    • Avoid "Risky Test" warnings by resetting counts in tearDown():
      $this->addToAssertionCount(MatcherAssert::getCount());
      MatcherAssert::resetCount();
      
  3. XML Matchers

    • Tip: Use hasXPath() for complex XML validation:
      assertThat($dom, hasXPath('//user[@active="true"]', 1));
      
  4. Performance

    • Gotcha: Overly nested allOf/anyOf can slow tests.
    • Tip: Pre-compile matchers for large datasets:
      $matcher = allOf(hasValue(1), hasValue(2));
      foreach ($data as $item) {
          assertThat($item, $matcher);
      }
      

Extension Points

  1. Custom Matcher Traits

    • Reuse logic across matchers:
      trait Validatable {
          abstract public function validate($value);
          public function matches($value) {
              return $this->validate($value);
          }
      }
      
  2. Matcher Factories

    • Create dynamic matchers:
      function rangeMatcher($min, $max) {
          return allOf(greaterThanOrEqualTo($min), lessThanOrEqualTo($max));
      }
      // Usage: assertThat($age, rangeMatcher(18, 99));
      
  3. Integration with Laravel

    • Tip: Use in FormRequest validation:
      public function rules() {
          return [
              'email' => ['required', 'string', new ValidEmailMatcher()]
          ];
      }
      
  4. Mocking with Hamcrest

    • Pattern: Validate mock interactions:
      $mock->expects($this->once())
           ->method('process')
           ->with($this->callback(function ($data) {
               return assertThat($data, hasKey('status', equalTo('pending')));
           }));
      
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata