Network mocking has long been treated as something only Playwright does. TestFly adds Chrome DevTools Protocol (CDP) interception and network throttling to Selenium 4 in Java. You can simulate offline mode, throttle the connection to slow 3G, stub third-party API responses and fail tests automatically on browser JavaScript errors, all without an external proxy server.
Why frontend tests need network interception
A single page application (SPA) talks to many backends: distributed microservices, third-party payment gateways, analytics trackers. In traditional Selenium tests this caused trouble:
- To test an edge case such as a 500 Internal Server Error or a slow payment response, you had to change backend database state or configure a proxy server such as BrowserMob Proxy.
- Slow third-party widgets and CDN outages made tests flaky.
- JavaScript errors in the browser console went unnoticed unless an explicit assertion failed.
TestFly uses Selenium 4's native CDP bridge to intercept and modify HTTP traffic at the browser process level.
Simulating slow 3G and offline mode
Mobile-first web apps need to be tested on poor connections:
package io.testfly.examples.network;
import io.testfly.network.NetworkSpeed;
import io.testfly.test.BaseTest;
import org.testng.annotations.Test;
public class NetworkThrottlingTest extends BaseTest {
@Test
public void testOfflineBannerVisibility() {
open("/dashboard");
// 1. Emulate instant network disconnection
network().emulateOffline();
// 2. Perform action requiring network
find("#sync-btn").click();
// 3. Verify offline warning UI appears immediately
assertThat(find("#offline-alert")).hasText("You are currently offline");
// 4. Restore regular network speed
network().resetThrottling();
}
@Test
public void testSlow3GSpinnerState() {
// Emulate realistic mobile latency: 2000ms latency, 400kbps download
network().throttle(NetworkSpeed.SLOW_3G);
open("/heavy-report");
assertThat(find(".loading-spinner")).isVisible();
}
}
Mocking backend API responses (stubbing)
You can simulate server failures or return custom JSON without touching the backend environment:
@Test
public void testPaymentGateway500ErrorHandling() {
// Intercept outgoing POST requests to payment service and return HTTP 500
network().intercept(route -> route
.matchingUrl("**/api/v1/charge")
.respondWith(500, "{\"error\": \"Payment processor unavailable\"}")
);
open("/checkout");
find("#pay-btn").click();
// Verify graceful error message shown to user
assertThat(find(".error-toast")).hasText("Payment processor unavailable, please try again.");
}
Catching silent console errors
An uncaught JavaScript exception can break the page for users even when every DOM assertion passes. TestFly's ConsoleErrorCollector watches the browser logs:
```yaml title="testfly.yml"
browser:
captureConsoleErrors: true
failOnConsoleErrors: true # Fails the test if severe JS errors are detected
When a severe JavaScript error occurs (`Uncaught TypeError`, or a `404 Not Found` for a critical script), TestFly logs the stack trace and fails the test with diagnostic context you can act on.
## FAQ
### Does TestFly require a separate proxy server like BrowserMob?
No. TestFly talks to the browser engine over the Chrome DevTools Protocol (CDP) WebSocket, so there are no extra ports, proxies or certificates to set up.
### Does CDP network interception work with headless Chrome?
Yes. Headful and headless Chrome/Chromium both support CDP network interception in CI/CD environments.
### Can I mock response headers and status codes?
Yes. The fluent `respondWith()` builder lets you override headers (for example `Content-Type: application/json` or CORS headers) and return any HTTP status code.
---
*Originally published on [hakangul.lovable.app](https://hakangul.lovable.app/blog/testfly-part-11-selenium-cdp-network-interception-and-mocking).*
Top comments (0)