---
title: "Testing an import"
manual: "TYPO3 EXT:thuecat"
version: "main"
permalink: "https://docs.typo3.org/permalink/werkraummedia/thuecat:developers-import-testing@main"
source: "Developers/Import/Testing.rst"
rendered: "2026-10-09T11:47:03+00:00"
---

# Testing an import {#developers-import-testing}

Import behaviour is tested with functional tests: a real database, a real DataHandler, and upstream
responses served from fixture files instead of the network.

## The test case {#the-test-case}

Import tests extend `\WerkraumMedia\ThueCat\Tests\Functional\AbstractImportTestCase`.
Read it before writing the first test; most of what a test needs is already there.

-   **Upstream responses**

    Every request a run makes has to be announced. `expectFetch()` serves a JSON-LD file for one
    URL, `expectNotFound()` answers `404`, `expectFailure()` answers any other status. A
    request nobody announced fails the test, and so does an announced request that never happened. A
    test therefore also documents exactly what a run fetches.

-   **Fixture files**

    Response bodies live under `Tests/Functional/Fixtures/Import/Guzzle/`, in a path mirroring
    the URL: host, path, then the resource id as file name.

-   **Database state**

    Pages, existing records and configurations are seeded from PHP data sets in
    `Tests/Functional/Fixtures/Import/`; expected states after an import live in
    `Tests/Functional/Assertions/Import/`.

-   **Reading results**

    `countRows()`, `fetchUidByRemoteId()` and `fetchRowByRemoteId()` query the
    database ignoring deleted rows, but no other restriction — hidden records and every language
    count. Use them instead of building queries in the test.

[`werkraummedia/events`](https://packagist.org/packages/werkraummedia/events) must be among the extensions a functional test loads. TYPO3 13
enforces the dependency; 14 tolerates its absence, so a test can pass on one version and fail on the
other.

## Habits that keep tests honest {#habits-that-keep-tests-honest}

-   **Count the default language**

    A table holds translations too. A count over the whole table passes for the wrong reasons;
    look records up by `remote_id` instead.

-   **Seed instead of importing twice**

    A re-import test seeds the rows a previous run would have left and imports once. Running the
    import twice in one test mostly proves that a run does what a run does.

-   **Test removal along with addition**

    A new relation needs a test that removes it, and one where a fetch fails next to a surviving
    entry, see [Sets of shared targets](https://docs.typo3.org/permalink/werkraummedia/thuecat:developers-import-relation-sets@main).

-   **Use placeholders for structural roles**

    Where a fixture needs a value that must not match anything real — an unmapped type, a foreign
    host — use an obviously invented one, not a real upstream URI.

The PHPUnit configuration ships with the package as `phpunit.xml.dist`.
