diff --git a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
index 5bf2f49eba..2862c678c2 100644
--- a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
+++ b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
@@ -56,6 +56,7 @@ public function testGoTo() {
     $this->assertStringNotContainsString('</html>', $text);
 
     // Response includes cache tags that we can assert.
+    $this->assertSession()->responseHeaderExists('X-Drupal-Cache-Tags');
     $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Tags', 'http_response rendered');
 
     // Test that we can read the JS settings.
@@ -74,6 +75,7 @@ public function testGoTo() {
     $this->drupalGet('system-test/header', [], [
       'Test-Header' => 'header value',
     ]);
+    $this->assertSession()->responseHeaderExists('Test-Header');
     $returned_header = $this->getSession()->getResponseHeader('Test-Header');
     $this->assertSame('header value', $returned_header);
   }
@@ -226,6 +228,16 @@ public function testLinkNotExistsExact() {
     $this->assertSession()->linkNotExistsExact('foo|bar');
   }
 
+  /**
+   * Tests responseHeaderDoesNotExist() functionality.
+   *
+   * @see \Drupal\Tests\WebAssert::responseHeaderDoesNotExist()
+   */
+  public function testResponseHeaderDoesNotExist() {
+    $this->drupalGet('test-pipe-char');
+    $this->assertSession()->responseHeaderDoesNotExist('Foo-Bar');
+  }
+
   /**
    * Tests linkNotExistsExact() functionality fail.
    *
diff --git a/core/tests/Drupal/FunctionalTests/WebAssertTest.php b/core/tests/Drupal/FunctionalTests/WebAssertTest.php
new file mode 100644
index 0000000000..f15921af5b
--- /dev/null
+++ b/core/tests/Drupal/FunctionalTests/WebAssertTest.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Drupal\FunctionalTests;
+
+use Drupal\Tests\BrowserTestBase;
+use PHPUnit\Framework\AssertionFailedError;
+
+/**
+ * Tests WebAssert functionality.
+ *
+ * @group browsertestbase
+ * @coversDefaultClass \Drupal\Tests\WebAssert
+ */
+class WebAssertTest extends BrowserTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'test_page_test',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * @covers ::responseHeaderExists
+   */
+  public function testResponseHeaderExists() {
+    $this->drupalLogin($this->drupalCreateUser());
+    $this->drupalGet('test-page');
+    $this->expectException(AssertionFailedError::class);
+    $this->expectExceptionMessage("Failed asserting that the response has a 'does-not-exist' header.");
+    $this->assertSession()->responseHeaderExists('does-not-exist');
+  }
+
+  /**
+   * @covers ::responseHeaderDoesNotExist
+   */
+  public function testResponseHeaderDoesNotExist() {
+    $this->drupalLogin($this->drupalCreateUser());
+    $this->drupalGet('test-page');
+    $this->expectException(AssertionFailedError::class);
+    $this->expectExceptionMessage("Failed asserting that the response does not have a 'X-Drupal-Cache-Tags' header.");
+    $this->assertSession()->responseHeaderDoesNotExist('X-Drupal-Cache-Tags');
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Constraints/ResponseHeaderExists.php b/core/tests/Drupal/Tests/Constraints/ResponseHeaderExists.php
new file mode 100644
index 0000000000..351550da04
--- /dev/null
+++ b/core/tests/Drupal/Tests/Constraints/ResponseHeaderExists.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace Drupal\Tests\Constraints;
+
+use PHPUnit\Framework\Constraint\Constraint;
+
+/**
+ * Asserts that a response header exists.
+ */
+class ResponseHeaderExists extends Constraint {
+
+  /**
+   * The header to be tested.
+   *
+   * @var string
+   */
+  protected $header;
+
+  /**
+   * Constructs a ResponseHeaderExists object.
+   *
+   * @param string $header
+   */
+  public function __construct($header) {
+    $this->header = $header;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function matches($other): bool {
+    if (is_array($other)) {
+      return array_key_exists($this->header, $other);
+    }
+
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function toString(): string
+  {
+    return 'has a ' . $this->exporter()->export($this->header) . ' header';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function failureDescription($other): string {
+    return 'the response ' . $this->toString();
+  }
+}
diff --git a/core/tests/Drupal/Tests/WebAssert.php b/core/tests/Drupal/Tests/WebAssert.php
index 7b296263ae..3e67197681 100644
--- a/core/tests/Drupal/Tests/WebAssert.php
+++ b/core/tests/Drupal/Tests/WebAssert.php
@@ -10,6 +10,10 @@
 use Behat\Mink\Session;
 use Drupal\Component\Utility\Html;
 use Drupal\Core\Url;
+use Drupal\Tests\Constraints\ResponseHeaderExists;
+use PHPUnit\Framework\Assert;
+use PHPUnit\Framework\Constraint\ArrayHasKey;
+use PHPUnit\Framework\Constraint\LogicalNot;
 
 /**
  * Defines a class with methods for asserting presence of elements during tests.
@@ -55,6 +59,32 @@ protected function cleanUrl($url) {
     return parent::cleanUrl($url);
   }
 
+  /**
+   * Asserts that the current response header has a specific entry.
+   *
+   * @param string $name
+   *   The name of the header entry to check existence of.
+   */
+  public function responseHeaderExists(string $name, string $message = ''): void {
+    $headers = $this->session->getResponseHeaders();
+    $constraint = new ResponseHeaderExists($name);
+    Assert::assertThat($headers, $constraint, $message);
+  }
+
+  /**
+   * Asserts that the current response header does not have a specific entry.
+   *
+   * @param string $name
+   *   The name of the header entry to check existence of.
+   */
+  public function responseHeaderDoesNotExist(string $name, string $message = ''): void {
+    $headers = $this->session->getResponseHeaders();
+    $constraint = new LogicalNot(
+      new ResponseHeaderExists($name)
+    );
+    Assert::assertThat($headers, $constraint, $message);
+  }
+
   /**
    * Checks that specific button exists on the current page.
    *
