# How to Mock Web Requests in GenLayer Direct Tests

> Mock web requests in GenLayer direct tests using direct_vm.mock_web. Intercept HTTP calls and return controlled responses for reliable testing.

- Repository: [GenLayer Labs/genlayer-project-boilerplate](https://github.com/genlayerlabs/genlayer-project-boilerplate)
- Tags: how-to-guide
- Published: 2026-08-20

---

**Use the `direct_vm.mock_web(regex_pattern, response_dict)` method to intercept HTTP calls made via `gl.nondet.web` and return controlled responses instead of hitting live endpoints.**

GenLayer's direct testing mode executes contracts in-memory using the `direct_vm` fixture, eliminating the need for a live Studio deployment. This approach, implemented in the `genlayerlabs/genlayer-project-boilerplate` repository, allows you to simulate nondeterministic web interactions with deterministic mocks for faster, isolated test runs.

## The mock_web API Signature

The `direct_vm` fixture provides the `mock_web` method to register URL patterns and their fabricated responses. According to the implementation in [`tests/direct/conftest.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/tests/direct/conftest.py), the method signature is:

```python
direct_vm.mock_web(regex_pattern, response_dict)

```

**Parameters:**

- `regex_pattern` — A Python regular expression string matched against the request URL.
- `response_dict` — A dictionary containing at least `"status"` (HTTP status code) and `"body"` (response payload as string or bytes).

When the contract code calls `gl.nondet.web.get`, `post`, or `render`, the VM checks its internal lookup table first. A matching regex short-circuits the actual network request and returns the supplied mock response.

## Practical Mocking Patterns

### Basic GET and POST Interception

To mock simple HTTP requests, register a pattern before invoking the contract method. This example from [`tests/direct/test_views.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/tests/direct/test_views.py) intercepts sports data requests:

```python
def test_simple_mock(direct_vm, direct_deploy):
    contract = direct_deploy("contracts/football_bets.py")
    
    direct_vm.mock_web(
        r".*bbc\.com/sport/football/scores-fixtures.*",
        {"status": 200, "body": "Match results available."},
    )
    
    contract.some_method_that_fetches()

```

### Combining Web and LLM Mocks

Complex workflows often require mocking both external APIs and LLM parsing. The `mock_web` method works alongside `mock_llm` to isolate multi-step nondeterministic operations:

```python
def test_resolve_bet(direct_vm, direct_deploy, direct_alice):
    contract = direct_deploy("contracts/football_bets.py")
    direct_vm.sender = direct_alice

    # Mock the web request

    direct_vm.mock_web(
        r".*bbc\.com/sport/football/scores-fixtures.*",
        {"status": 200, "body": "Match results available."},
    )
    
    # Mock the LLM parsing response

    direct_vm.mock_llm(
        r".*Extract the match result.*",
        json.dumps({"score": "1:0", "winner": 1}),
    )
    
    contract.resolve_bet("2024-06-20_spain_italy")

```

### Updating Mocks Mid-Test

When a test case invokes multiple web requests requiring different responses, use `clear_mocks()` to reset the internal lookup table before registering new patterns:

```python
def test_multiple_resolves(direct_vm, direct_deploy, direct_alice):
    contract = direct_deploy("contracts/football_bets.py")
    direct_vm.sender = direct_alice

    # First match

    direct_vm.mock_web(r".*bbc\.com.*", {"status": 200, "body": "data1"})
    contract.resolve_bet("match1")

    # Reset and reconfigure for second match

    direct_vm.clear_mocks()
    direct_vm.mock_web(r".*bbc\.com.*", {"status": 200, "body": "data2"})
    contract.resolve_bet("match2")

```

### Mocking Screenshot Rendering

For contracts using `gl.nondet.web.render` in screenshot mode, provide a bytes payload (typically empty) in the `response_dict`:

```python
def test_mock_web_intercepts_render_screenshot(direct_vm, direct_deploy, visual_contract_path):
    direct_vm.mock_web(r".*", {"status": 200, "body": b""})
    contract = direct_deploy(visual_contract_path)
    contract.render_screenshot()  # Calls gl.nondet.web.render(..., mode='screenshot')

```

This pattern is demonstrated in [`tests/integration/test_new_features.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/tests/integration/test_new_features.py).

## How the Interception Works

Under the hood, `mock_web` registers patterns in a lookup table inside the `DirectVM` instance. When contract code executes `gl.nondet.web.get(url, ...)` or similar methods, the VM checks this table first. A matching regex short-circuits the actual network request and returns the supplied mock response.

This mechanism applies identically to `render` calls for both `text`/`html` and `screenshot` modes. For textual renders, the `"body"` field contains the HTML or text content; for screenshot mocks, the framework accepts a byte string (commonly empty `b""`).

## Summary

- Use `direct_vm.mock_web(regex, {"status": int, "body": str|bytes})` to intercept URLs matching the pattern.
- Register mocks before contract invocation; subsequent matching calls return the fabricated response.
- Call `direct_vm.clear_mocks()` to reset state between test scenarios.
- Supply bytes payloads (e.g., `b""`) when mocking screenshot renders.
- Reference implementations exist in [`tests/direct/test_views.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/tests/direct/test_views.py) and [`tests/integration/test_new_features.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/tests/integration/test_new_features.py).

## Frequently Asked Questions

### Can I mock multiple different endpoints in the same test?

Yes. Call `mock_web` multiple times with different regex patterns before executing the contract method. Each pattern is stored in the VM's lookup table and matched independently against outgoing requests made via `gl.nondet.web`.

### What happens if a web request doesn't match any mock pattern?

If no registered regex matches the request URL, the VM will attempt to execute the actual network call or raise an error depending on the direct test configuration. Always ensure your patterns cover all URLs the contract might request during the test to maintain deterministic behavior.

### Does mock_web work with POST requests and custom headers?

Yes. The `mock_web` method intercepts any `gl.nondet.web` call including `post` and `render`. While the response dictionary primarily defines `status` and `body`, the interception occurs at the VM level regardless of the HTTP method or headers used in the contract code.

### How do I mock paginated or sequential API calls?

Use `clear_mocks()` between contract invocations to update the response for subsequent calls. Alternatively, register multiple distinct patterns if the URLs differ, such as by including page numbers or query parameters in the regex.