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

Service Container Extension Laravel Package

friends-of-behat/service-container-extension

Declare custom Symfony DI services in Behat without writing a full extension. Import XML/YAML/PHP service definition files via behat.yml so your contexts and helpers can be wired through the Behat service container.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Laravel/Behat Synergy: The package leverages Symfony’s DI container, which Laravel already integrates via Illuminate/Container. This enables seamless injection of test-specific services (e.g., mock repositories, API clients) into Behat’s context without polluting Laravel’s production container. Aligns with Laravel’s principle of environment-specific configurations (e.g., .env.testing).
  • BDD Workflow Enhancement: Addresses gaps in Behat’s native DI support by allowing declarative service definitions (XML/YAML/PHP) for complex test setups, such as:
    • Multi-layered test data: Injecting a TestUserFactory into feature contexts.
    • External system mocks: Replacing live API calls with MockStripeClient in payment workflow tests.
    • Cross-cutting concerns: Centralizing test utilities (e.g., TestLogger, ScreenshotService) via DI.
  • Isolation: Services are scoped to Behat’s container, preventing leaks into Laravel’s runtime. Critical for projects using shared containers (e.g., Laravel’s app() in tests).

Integration Feasibility

  • Minimal Laravel Overhead: No changes to Laravel’s core or service providers required. Integration is confined to:
    1. Composer: Install in composer.json under require-dev.
    2. Behat Config: Add to behat.yml with path references to Laravel’s config structure (e.g., features/bootstrap/config/services.yml).
    3. Service Definitions: Use Laravel-like syntax (YAML/PHP) for familiarity.
  • Existing Laravel Patterns:
    • Config Files: Mirror Laravel’s config/services.php with services.yml for Behat.
    • Environment Variables: Reference .env.testing in service definitions (e.g., parameters: { test_db: "%env(TEST_DB_DSN)%" }).
    • Autoloading: Leverage Laravel’s PSR-4 autoloading for service classes.
  • Tooling Compatibility:
    • Laravel Forge/Laravel Vapor: No impact; package is dev-only.
    • PestPHP: Can coexist if Behat is used for BDD alongside Pest for unit tests.
    • CI/CD: Requires --dev flag in composer install for Behat runs (standard for Laravel).

Technical Risk

  • Deprecation Risk:
    • Behat 4+: Last release (2020) predates Behat 4’s container changes. Risk of breaking changes if upgrading Behat.
    • PHP 8.2+: Claims PHP 8.0+ support, but no explicit testing for newer features (e.g., enums, attributes).
    • Symfony DI: Underlying Symfony components may evolve (e.g., Definition class changes).
    • Mitigation: Pin versions in composer.json and monitor for forks (e.g., behat/behat:^4.0 + this package).
  • Configuration Complexity:
    • Multiple Formats: XML/YAML/PHP may introduce maintenance overhead for teams preferring PHP-only (e.g., Laravel’s bind()).
    • Scope Management: Misconfigured service scopes (e.g., singleton vs. prototype) could cause flaky tests.
    • Mitigation: Standardize on YAML/PHP and document scoping rules in a TESTING.md.
  • Container Conflicts:
    • Laravel vs. Behat: Services defined here won’t auto-resolve in Laravel’s container. Risk of accidental sharing if not isolated.
    • Mitigation: Prefix service IDs (e.g., behat.test_api_client) and avoid overlapping with Laravel’s bindings.
  • Testing Quirks:
    • Service Lifecycle: Behat’s container lifecycle (e.g., per-scenario vs. per-test) may differ from Laravel’s. Example: A singleton in Behat might not behave like Laravel’s app()->singleton().
    • Mitigation: Test with behat --stop-on-failure and validate service states across scenarios.

Key Questions

  1. Behat Version Lock:

    • Question: Is the team using Behat 3.x or 4.x? If 4.x, test compatibility with this package’s last release (2020).
    • Action: Run behat --version and check Behat’s upgrade guide for container changes.
  2. Service Isolation:

    • Question: Are any Laravel services being injected into Behat contexts? If so, how will conflicts be handled?
    • Action: Audit AppServiceProvider for shared test services and document exclusion rules.
  3. PHP Version Support:

    • Question: What PHP version is the project targeting (e.g., 8.1, 8.2)? Test the package with php -v and composer validate.
    • Action: Add a phpunit.xml check:
      <php>
          <env name="PHP_VERSION" value=">=8.1.0"/>
      </php>
      
  4. Long-Term Maintenance:

    • Question: Is this package a stopgap or a core part of the testing strategy?
    • Action: If critical, allocate time to:
      • Fork the repo and update for Behat 4+.
      • Replace with Laravel’s native testing tools (e.g., createMock() + partialMock()) if overkill.
  5. Team Familiarity:

    • Question: Does the team have experience with Symfony’s DI (XML/YAML) or Laravel’s service bindings?
    • Action: Provide a 1-hour workshop on:
      • Defining services in services.yml (parallel to Laravel’s config/services.php).
      • Injecting services into Behat contexts/hooks.

Integration Approach

Stack Fit

  • Primary Use Case: Laravel projects using Behat for BDD where test-specific services require DI (e.g., mocking APIs, injecting factories, or sharing utilities across contexts).
  • Secondary Use Case: Projects integrating third-party SDKs (e.g., Stripe, Twilio) into tests, where custom service wrappers are needed.
  • Non-Laravel PHP: Limited value; native alternatives (e.g., PHPUnit’s getMockBuilder()) may suffice.
  • Symfony Projects: Directly applicable if using Behat + Symfony DI outside Laravel.

Migration Path

  1. Preparation Phase:

    • Audit: Identify manual service instantiations in Behat tests (e.g., new TestUserRepository()).
    • Design: Map services to DI definitions (e.g., TestUserRepositoryservices.yml).
    • Tooling: Ensure composer.json has:
      "require-dev": {
          "friends-of-behat/service-container-extension": "^2.0"
      }
      
  2. Proof of Concept (PoC):

    • Step 1: Install the package and configure behat.yml:
      # behat.yml
      default:
          extensions:
              FriendsOfBehat\ServiceContainerExtension:
                  imports:
                      - "%paths.config%/behat/services.yml"
      
    • Step 2: Define a test service in features/bootstrap/config/services.yml:
      services:
          behat.test_user_repository:
              class: App\Tests\TestUserRepository
              arguments: ["@database_connection.testing"]
      
    • Step 3: Inject the service into a context:
      class UserContext {
          public function __construct(private TestUserRepository $repository) {}
          public function i_create_a_user() {
              $this->repository->create(['name' => 'John']);
          }
      }
      
    • Step 4: Run tests with ./vendor/bin/behat. Verify the service is resolved.
  3. Incremental Rollout:

    • Phase 1: Migrate one feature file to use DI (e.g., user.feature).
    • Phase 2: Replace hardcoded services in step definitions with container bindings.
    • Phase 3: Centralize service definitions in services.yml (avoid duplicating XML/PHP).
    • Phase 4: Add environment-specific configurations (e.g., services.testing.yml for CI).
  4. Configuration Standardization:

    • Naming Conventions: Prefix service IDs with behat. (e.g., behat.test_api_client).
    • Parameter Binding: Use Laravel’s .env.testing for dynamic values:
      parameters:
          test_api_url: "%env(TEST_API_URL)%"
      services:
          behat.test_api_client:
              class: App\Tests\TestApiClient
              arguments: ["@test_api_url"]
      
    • Laravel Path Integration: Reference Laravel’s config paths:
      imports:
          - "%paths.config%/behat/services.yml"
          - "%paths.config%/behat/services.ci.yml"  # CI-specific
      

Compatibility

  • Laravel-Specific:
    • **Service Prov
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
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