Nette Tester: HTTP testing has never been so easy
When was the last time you changed your server configuration, modified
.htaccess
, or rewrote nginx rules? And did you check if this
accidentally broke redirects, made robots.txt inaccessible, or exposed a hidden
directory to unauthorized users? Do you check this automatically, or do you just
manually click through the website hoping everything works fine?

With the new HttpAssert
class in Nette Tester 2.5.6, you can
automate all these critical checks and never have to worry that a configuration
change might break your website.
Imagine automatically verifying after every nginx configuration change:
// Critical paths are still accessible
HttpAssert::fetch('https://example.com/robots.txt')
->expectCode(200)
->expectHeader('Content-Type', contains: 'text/plain');
// Admin section is properly protected
HttpAssert::fetch('https://example.com/admin')
->expectCode(403);
// API endpoint works
HttpAssert::fetch('https://example.com/api/health')
->expectCode(200)
->expectBody(contains: '"status":"ok"');
All validation methods at your fingertips
HttpAssert
allows you to easily perform HTTP requests and verify
their status codes, headers, and response body content. The fetch()
method returns an HttpAssert
instance for subsequent verification
using a fluent interface. You can use the same pattern matching you know from
Assert::match().
HttpAssert::fetch('https://api.example.com/data')
// Status codes
->expectCode(200) // exact code
// Headers in every way
->expectHeader('Content-Type') // header must exist
->expectHeader('Content-Type', 'application/json') // exact value
->expectHeader('Content-Type', contains: 'json') // contains text
->expectHeader('Server', matches: 'nginx %a%') // pattern matching
// Response body
->expectBody('OK') // exact value
->expectBody(contains: '"success": true') // contains text
->expectBody(matches: '%A%"users":[%a%]%A%'); // matches pattern
The deny* methods are also available and support the same options as their expect* counterparts:
HttpAssert::fetch('https://api.example.com/data')
->denyCode(200) // must not be 200
->denyHeader('Content-Type') // header must not exist
->denyHeader('Content-Type', contains: 'json') // does not contain text
->denyHeader('Server', matches: 'nginx %a%') // does not match pattern
->denyBody('OK') // body must not have value
->denyBody(contains: '"success": true') // does not contain text
->denyBody(matches: '~exception|fatal~i'); // does not match pattern
Callback functions for advanced validation
Sometimes you need more than just simple comparisons. That's why HttpAssert supports callback functions in all verification methods. You can write your own validation logic while still using the elegant API:
HttpAssert::fetch('https://api.example.com/data')
->expectCode(fn($code) => $code === 200 || $code === 201)
->expectHeader('Content-Length', fn($length) => $length > 1000)
->expectBody(fn($body) => json_decode($body) !== null);
Intelligent redirect handling
You have full control over redirects – you can follow them or test them separately:
// Test redirect without following
HttpAssert::fetch('https://example.com/old-blog', follow: false)
->expectCode(301)
->expectHeader('Location', 'https://example.com/blog');
// Follow redirects to the end
HttpAssert::fetch('https://example.com/old-blog', follow: true)
->expectCode(200)
->expectBody(contains: 'Welcome to our new blog');
Flexible request configuration
Whether you're testing GET, POST, PUT, DELETE, or any other HTTP method, HttpAssert can handle it. And of course you can send a request body, headers, or cookies:
HttpAssert::fetch(
'https://api.example.com/protected',
method: 'POST',
headers: [
'Authorization' => 'Bearer ' . $token, // associative array
'Accept: application/json', // or as string
],
cookies: ['session' => $sessionId],
body: json_encode($data)
)
->expectCode(201)
->expectBody(contains: 'created');
Clear error messages
When a test fails, HttpAssert
tells you exactly what
went wrong:
Expected HTTP status code 200 but got 404
Header 'Content-Type' should contain 'json' but was 'text/html'
Body should contain 'success'
What else is new in Tester 2.5.6?
Besides HttpAssert
, version 2.5.6 also brings support for the
upcoming PHP 8.5, which will be released at the end of the year. Nette Tester
thus always stays one step ahead and ready for the latest PHP versions.
Try HttpAssert
and let us know how you like it!
Further reading
- Nette Http 3.2: change access to credentials
- Nette Utils 4.0: UTF-8, Finder and named arguments
- Nette Http 3.1: much smarter sessions
- Nette Assets: Finally unified API for everything from images to Vite
- PhpGenerator 3.6: news from PHP 8.1 and more
- Write Safer Code with the New Nette Database Documentation
Sign in to submit a comment