Making HTTP requests programmatically in Kernel tests

Last updated on
9 June 2026

HTTP requests using drupalGet()

While in general, Functional tests are designed for the testing of page loads, it's possible to test these in Kernel tests too. The advantage is that Kernel tests are much faster to run, because they only set up what they need to. The faster running time is particularly useful if many different combinations need to be tested for.

The trade-off is that some aspects of the Drupal site are not available, such as form submissions and session handling, and that more set-up is required (but you only set up the elements the test needs). See the documentation page on Setup tasks in Kernel tests for more information and examples.

Using Kernel tests for testing requests is particularly suited to:

  • Tests that check the output of a page.
  • Tests that only check the HTTP status of the response, for example when checking access to a page.
  • Tests that make non-HTML requests, such as testing REST endpoints, or AJAX responses.

Requests are made using the methods in Drupal\Tests\HttpKernelUiHelperTrait, which work similarly to those in Browser tests:

  • Use drupalGet() to make a request.
  • Use assertSession() to make assertions on the page content using Mink.
  • Configure your phpunit.xml file to have the content of the responses output as HTML files for debugging.

Limitations

Some things do not work the same as in Browser tests, or will need additional setup tasks:

  • Forms cannot be submitted. This functionality may be added in a future issue.
  • Session semantics differ from normal page requests. Do not rely on session state beyond its existence (no persistence or regeneration).
  • There is no logged in user. Use \Drupal\Tests\user\Traits\UserCreationTrait to set a current user (see below).
  • There is no active theme. To place blocks, a test must first install a theme and then set it as active.
  • Additional steps are needed for page caching modules to function. See \Drupal\Tests\Traits\Core\Cache\PageCachePolicyTrait for details.

User access

To make the request as a user with specific permissions, rather than the anonymous user, you need to set up the current user:

use Drupal\Tests\user\Traits\UserCreationTrait;

  use UserCreationTrait;

    // In your test or setup:
    $user = $this->createUser([
      'my permission',
    ]);
    $this->setCurrentUser($user);

Pitfalls

Making multiple requests within the same session can cause problems with code in Drupal that assumes that the code lifecycle is a single HTTP request.

Of particular note is the Entity access system, which currently uses a static class property as a cache (this is a bug in core). This means that the access data for an entity will be cached and not get invalidated when a change is made to the entity or to other parts of the site such as user permissions. The access cache should be flushed any time changes are made:

    $this->entityTypeManager->getAccessControlHandler('node')->resetCache();

Generally, be aware of:

  • Services, plugins, or other classes which store values as class properties.
  • Use of drupal_static().
  • Code which uses the main request rather than the current request from the request stack.

These are all issues which should be fixed, as they will cause problems with persistent app servers as well as in Kernel tests.

HTTP requests using the HTTP kernel

Prior to Drupal 11.3's addition of Drupal\Tests\HttpKernelUiHelperTrait, HTTP requests can be made in Kernel tests by calling the HTTP kernel:

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

function testMyTest() {
  $http_kernel = $this->container->get('http_kernel');

  $request = Request::create('/node/' . $node->id());

  $response = $http_kernel->handle($request);
  $this->assertEquals(Response::HTTP_FORBIDDEN, $response->getStatusCode());

If making a request for a REST resource, the Accept header must be set:

    $request = Request::create('/node/' . $node->id());
    $request->headers->set('Accept', 'application/json');

The same $request object can be passed to the HTTP kernel multiple times; there is no need to recreate it after making changes to the site to test a different case.

The content of the request can be obtained thus:

$content = $response->getContent();
// This allows use of the methods in AssertContentTrait.
$this->setRawContent($content);

Further reading

Help improve this page

Page status: No known problems

You can: