无独立服务器下用Behat/Mink测试Symfony 3.4 API的POST请求
Absolutely, you can test POST requests directly through Symfony's internal kernel—no external web server, Docker, or network calls required. Here are two practical approaches tailored to your Behat/Mink + CI/CD workflow:
1. Use Symfony's HttpKernel Directly in Your Behat Context
Behat's SymfonyExtension already gives you access to Symfony's kernel, which lets you simulate HTTP requests internally. You can inject the kernel into your context class and manually craft POST requests with JSON payloads.
First, ensure your context accepts the kernel via dependency injection (add this to your behat.yml if missing):
# behat.yml default: suites: default: contexts: - App\Features\Context\ApiContext: kernel: '@kernel'
Then implement the context with methods to send POST requests and validate responses:
<?php namespace App\Features\Context; use Behat\Behat\Context\Context; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class ApiContext implements Context { private $kernel; private $response; public function __construct(KernelInterface $kernel) { $this->kernel = $kernel; } /** * @When I send a POST request to :path with JSON payload: */ public function iSendAPostRequestToWithJsonPayload(string $path, string $jsonPayload) { $request = Request::create( $path, Request::METHOD_POST, [], [], [], ['CONTENT_TYPE' => 'application/json'], $jsonPayload ); // Handle the request internally using Symfony's kernel $this->response = $this->kernel->handle($request); } /** * @Then the response status code should be :statusCode */ public function theResponseStatusCodeShouldBe(int $statusCode) { if ($this->response->getStatusCode() !== $statusCode) { throw new \Exception(sprintf( 'Expected status code %d, got %d', $statusCode, $this->response->getStatusCode() )); } } /** * @Then the response should contain JSON with :key equal to :value */ public function theResponseShouldContainJsonWithEqualTo(string $key, string $value) { $responseData = json_decode($this->response->getContent(), true); if (!isset($responseData[$key]) || $responseData[$key] !== $value) { throw new \Exception(sprintf( 'Expected JSON key "%s" to be "%s", got "%s"', $key, $value, $responseData[$key] ?? 'null' )); } } }
Now you can write feature files that mirror your existing GET test style but support POST:
@function1 Scenario Outline: Test POST API endpoint When I send a POST request to "/api/v1/hello" with JSON payload: """ {"name": "Jay"} """ Then the response is JSON And the response status code should be 200 And the response should contain JSON with "message" equal to "Hello, Jay!"
2. Extend Mink to Support POST Requests (Familiar Syntax)
If you prefer to stick closer to Mink's existing step style, you can leverage the Symfony driver's underlying BrowserKit client to send POST requests internally—no external server needed.
Add this method to your existing Mink-enabled context:
/** * @When I send a POST request to :path with JSON: */ public function iSendAPostRequestToWithJson(string $path, string $json) { $session = $this->getSession(); $client = $session->getDriver()->getClient(); $client->request( Request::METHOD_POST, $path, [], [], ['CONTENT_TYPE' => 'application/json'], $json ); }
This works because Mink's Symfony driver uses BrowserKit, which interacts directly with the Symfony kernel. You can pair this with Mink's built-in assertions (like Then the response is JSON) for a seamless experience.
CI/CD Workflow Tips
- Both approaches run entirely within the PHP process—no need to start Apache, PHP-FPM, or any external server.
- Add
php bin/console cache:clear --env=testto your shell script to ensure a clean test environment. - Ensure your CI/CD runner installs all dev dependencies (run
composer installwithout--no-dev).
内容的提问来源于stack exchange,提问作者JayMore

