---
title: "Testovanie — Git for Laravel | Roundly"
description: "Git::fake() zaznamená každé volanie providera pre fasádu aj injektovaný manažér — naplňte odpovede, spustite kód bez HTTP a overte, čo odišlo."
url: https://roundly-consulting.com/sk/open-source/navody/git-for-laravel/testovanie
language: sk
---

[Všetky balíky](https://roundly-consulting.com/sk/open-source.md)

[Git for Laravel](https://roundly-consulting.com/sk/open-source/navody/git-for-laravel.md)

# Testovanie

Git::fake() nahradí manažér zaznamenávajúcim GitFake — pre fasádu aj pre všetko, čo si injektovalo GitManager — a vráti ho. Každý driver, ktorý vydá, je ProviderFake, ktorý naplníte dátami, žiadne HTTP neopustí proces (Http::preventStrayRequests()) a zaznamená sa každé volanie, či už prešlo plochými metódami drivera, handlom repo() / pullRequest() / installations(), cez webhooks() alebo batch(). Naplňte, čo váš kód číta, spustite ho a overte:

```php
use Illuminate\Support\Carbon;
use RoundlyConsulting\Git\Dto\Owner;
use RoundlyConsulting\Git\Dto\Repository;
use RoundlyConsulting\Git\Enums\ProviderName;
use RoundlyConsulting\Git\Facades\Git;

it('lists the connected repositories', function () {
    $fake = Git::fake();

    $fake->github()->seedRepositories([new Repository(
        provider: ProviderName::Github,
        id: '1',
        path: 'acme/api',
        name: 'api',
        description: null,
        defaultBranch: 'main',
        owner: new Owner(id: '1', name: 'acme', avatar: null),
        createdAt: Carbon::now(),
        lastActivityAt: Carbon::now(),
    )]);

    // run code that calls Git::github()->repositories() ...

    Git::assertSent(ProviderName::Github, 'repositories');
    Git::assertNotSent(ProviderName::Github, 'createRepository');
});
```

## Prihlasovacie údaje vo fake

Fake sa prihlasuje presne tak ako skutočný manažér — len s prihlasovacími údajmi nikdy nič nepodpisuje ani neposiela. Každé volanie Git::github() / githubApp() / gitlab() / bitbucket() / provider() dostane vlastný fake driver, ktorý zdieľa seedy a záznamy providera, s odovzdanými údajmi, inak s nastavenými, inak bez nich:

- Zápis — aj listWebhooks() — bez prihlasovacích údajov vyhodí InvalidCredentialsException::missing(); čítania zostávajú anonymné a isAuthenticated() tomu zodpovedá.
- Typ údajov, ktorý platforma neprijíma, sa odmietne (unsupported() — napríklad OauthToken na Bitbuckete) a authenticationMethods() vracia zoznam skutočného drivera.
- installations() vyžaduje GithubApp a installationRepositories() GithubAppToken (wrongCredentialType()); Git::githubApp() bez nastavenej aplikácie vyhodí missingAppConfig().
- Dáta plňte cez fakeFor(ProviderName::…), ktorý prihlasovacie údaje nepotrebuje.

Testy hostiteľskej aplikácie preto nastavia fiktívne prihlasovacie údaje — akékoľvek hodnoty, nič sa nepodpisuje — alebo ich odovzdajú pri každom volaní (Git::github(Token::from('test'))):

```php
config([
    'git.providers.github.token' => 'test-token',            // writes on Git::github()
    'git.providers.github.app.id' => '123',                   // Git::githubApp(): numeric id
    'git.providers.github.app.private_key' => 'test-key',     // … and any non-blank key
    // 'git.providers.github.app.installation_id' => '456',   // Git::github() as the installation
]);
```

## Asercie

Každá asercia pomenúva metódu drivera, na ktorú volanie dorazilo — handly volajú ploché metódy, takže ->pullRequest(12)->merge() sa zaznamená ako mergePullRequest — a callback v assertSent() / assertNotSent() dostane argumenty tejto metódy pozične. Po Git::fake() fungujú všetky staticky na fasáde aj na vrátenom fake:

```php
// run code that calls Git::github()->repo('acme/app')->pullRequest(12)->merge() ...

Git::assertSent(ProviderName::Github, 'mergePullRequest');
Git::assertSent(ProviderName::Github, 'mergePullRequest', fn (string $path, int $number) => $number === 12);
Git::assertSentTimes(ProviderName::Github, 'approvePullRequest', 1);
Git::assertNotSent(ProviderName::Github, 'closePullRequest');
Git::assertNotSent(ProviderName::Github, 'mergePullRequest', fn (string $path) => $path === 'acme/billing');
Git::assertNothingSent(ProviderName::Gitlab);   // nothing reached GitLab
Git::assertNothingSent();                       // nothing reached any provider
Git::assertBatched(ProviderName::Github, 'languages');
Git::assertNotBatched(ProviderName::Github, 'repositories');
Git::assertRepositoryCreated('new-repo');
Git::assertRepositoryCreated('new-repo', owner: 'acme', template: 'acme/package-template');
Git::assertNoRepositoryCreated();
```

| Metóda | Prejde, keď |
| --- | --- |
| `assertSent(provider, method, ?callback)` | Metóda drivera bola zavolaná — a s callbackom mu vyhovujú argumenty aspoň jedného volania (odovzdané pozične). |
| `assertSentTimes(provider, method, times)` | Metóda drivera bola zavolaná presne toľkokrát. |
| `assertNotSent(provider, method, ?callback)` | Žiadne (callbacku vyhovujúce) volanie neprebehlo. |
| `assertNothingSent(?provider)` | Neprebehlo žiadne volanie — alebo žiadne na daného providera. |
| `assertBatched(provider, method) / assertNotBatched(…)` | Dávka batch()->{method}() prebehla / neprebehla. |
| `assertRepositoryCreated(name, ?owner, ?template)` | Volanie createRepository() zodpovedá názvu — a ak sú zadané, aj vlastníkovi a šablóne. |
| `assertNoRepositoryCreated()` | Neprebehlo žiadne volanie createRepository(). |
| `assertWorkflowDispatched(workflow, ?ref, ?inputs, ?repository)` | Workflow bol spustený — ak sú zadané, tak na danom refe a v danom repozitári; vstupy musia sedieť presne: rovnaké názvy, hodnoty aj typy, v ľubovoľnom poradí. |
| `assertNoWorkflowDispatched()` | Na žiadnom provideri sa nespustil žiadny workflow. |
| `assertWorkflowRunCancelled(runId, ?repository)` | Run bol zrušený — ak je zadaný, tak v danom repozitári. |
| `assertNoWorkflowRunCancelled()` | Na žiadnom provideri sa nezrušil žiadny run. |
| `recorded(provider, ?method)` | Vráti zoznam RecordedCall (method, arguments) od najstaršieho. |
| `fakeFor(provider)` | Vráti jediný ProviderFake daného providera na naplnenie dátami — neprihlásený, takže plnenie nevyžaduje prihlasovacie údaje. |

## Zaznamenané volania

```php
$calls = Git::recorded(ProviderName::Github, 'mergePullRequest'); // list<RecordedCall>

$calls[0]->method;     // "mergePullRequest"
$calls[0]->arguments;  // ['acme/app', 12, MergeMethod::Merge, null, null, null]

Git::recorded(ProviderName::Github);                  // every GitHub call, oldest first
Git::fakeFor(ProviderName::Gitlab)->seedRepositories([$repositoryDto]);
```

## Injektované manažéry

Keďže GitFake dedí z GitManager, fake dostane aj trieda, ktorá si manažér injektuje cez konštruktor — nič netreba prebindovať:

```php
use RoundlyConsulting\Git\Facades\Git;

it('merges the release pull request', function () {
    config(['git.providers.github.token' => 'test-token']); // the fake authenticates like production

    Git::fake()->github()->seedMergeCommit('abc123');

    $sha = app(ShipRelease::class)('acme/app', 12);   // constructor-injects GitManager

    expect($sha)->toBe('abc123');
    Git::assertSent(ProviderName::Github, 'mergePullRequest', fn (string $path, int $number) => $number === 12);
});
```

## Správanie bez seedu

Dvojník pokrýva celý kontrakt Provider — každé čítanie, zápis, vyhľadanie inštalácie aj dopyt na commity — takže hostiteľská aplikácia pri raste nikdy nenarazí na nedefinovanú metódu. Jeho správanie určujú tri pravidlá:

| Druh volania | Správanie bez seedu |
| --- | --- |
| Zoznamové čítania (pullRequests, issues, tags, releases, contributors, branches, languages) | Prázdna stránka — skutočná odpoveď providera. Naplnené zoznamy sa stránkujú ako na platforme: veľkosť stránky menšia ako 1 vyhodí výnimku, väčšia ako 100 sa obmedzí (pri pullRequests() na Bitbuckete na 50) a položky sa rozdelia po stránkach s nastaveným hasMore. |
| Čítania jedného zdroja (repository, commit, contents, issue, release, installation, branch, workflowRun) | Vyhodí RuntimeException s názvom seedera, ktorý treba zavolať. |
| Zápisy (createPullRequest, comment, mergePullRequest, …) | Výsledok sa zostaví zo vstupu — keď volanie prejde kontrolami prihlásenia a vstupu, ktoré spúšťa skutočný driver. |

Každý fake driver podporuje presne to, čo jeho skutočný driver: supports(), capabilities() aj featureMatrix() odpovedajú rovnako a operácia, ktorú platforma nemá, vyhodí rovnakú FeatureNotSupportedException ešte pred zaznamenaním — fake Bitbucket odmietne ->pullRequest(1)->merge() rovnako ako Bitbucket, takže test nemôže prejsť pri toku, ktorý by produkcia odmietla. Vo fake bežia aj vlastné kontroly vstupu drivera — filtre commitov podľa autora či dátumu na Bitbuckete, komentár na GitLabe bez cieľa, komentár k issue na Bitbuckete, createRepository() na Bitbuckete s autoInit alebo defaultBranch, nečíselný owner na GitLabe, neaktívny webhook na GitLabe či webhook s neznámou udalosťou — a rovnako pravidlo veľkosti stránky, chybný odkaz pre batch()->pullRequest() aj porovnanie udalostí v register().

## Seedery

Všetky sú reťaziteľné: seedRepositories, seedRepository, seedCreatedRepository, seedCommits, seedCommit, seedBranches, seedPullRequests, seedPullRequest, seedIssues, seedIssue, seedTags, seedReleases, seedRelease, seedContents, seedComparison, seedContributors, seedLanguages, seedSearchResults, seedComment, seedMergeCommit, seedApprovalState, seedSubmittedReview, seedPullRequestReviews, seedUser, seedInstallation, seedInstallations, seedWebhooks, seedCreatedWebhook, seedBatch, seedBranch, seedActivity, seedWorkflowRuns, seedWorkflowRun, seedWorkflowJobs, seedDispatchWithoutRunDetails.

```php
use RoundlyConsulting\Git\Batch\BatchResult;

$fake->github()
    ->seedPullRequest($pullRequestDto)
    ->seedMergeCommit('abc123');

// ->pullRequest(n)->close() returns the seeded PR with state Closed; ->merge() returns 'abc123'

$fake->fakeFor(ProviderName::Gitlab)->seedRepositories([$repositoryDto]);

$fake->github()->seedBatch('languages', new BatchResult(['acme/api' => ['PHP' => 100]], []));
```

- review() nepotrebuje seed: vráti stav, ktorý udalosť skutočne znamená (Comment → COMMENTED, nikdy APPROVED), takže test overujúci verdikt nemôže prejsť proti fake, ak by proti GitHubu zlyhal; seedSubmittedReview() ho prepíše, keď test potrebuje konkrétne id alebo URL.
- seedPullRequestReviews($reviews, $comments) plní obe polovice zvlášť, pretože skutočné volanie ich číta z dvoch endpointov.
- createRepository() zostaví vrátené Repository zo vstupu — owner určí cestu a Owner; defaultBranch, prípadne main, ak autoInit alebo šablóna žiadali commit, inak prázdna hodnota, určí predvolenú vetvu — pokiaľ nie je nastavený seedCreatedRepository().
- Zámerné náhrady: installationRepositories() číta rovnaké dáta ako repositories(), installations()->all() použije jedinú naplnenú inštaláciu, searchRepositories() siahne po naplnených repozitároch, pullRequest() / issue() / release() vezmú prvú položku svojho zoznamu a pull request bez seedu sa vráti s číslom, na ktoré ste sa pýtali.
- Fiktívna URL na klonovanie nesie používateľské meno, ktoré používa skutočný driver — token (pri inštalačnom tokene x-access-token) na GitHube, oauth2 na GitLabe, vaše na Bitbuckete — a pri obnoviteľných údajoch zástupné tajomstvo; prázdne tajomstvo si ponechá dvojbodku, rovnako ako pri skutočných driveroch.

## GitHub Actions vo fake

Fake zvládne celý tok spustenie → nájdenie → sledovanie → zrušenie. Na rozdiel od commits(), ktorého filtre sa len zaznamenajú, sa filtre runov a pokusy jobov naozaj uplatnia — ignorovaný filter by vrátil run iného workflowu:

```php
use RoundlyConsulting\Git\Enums\ProviderName;
use RoundlyConsulting\Git\Facades\Git;

config(['git.providers.github.token' => 'test-token']);   // dispatch and cancel need a credential

$fake = Git::fake();
$actions = Git::github()->repo('acme/app')->actions();

$dispatched = $actions->dispatch('deploy.yml', 'refs/heads/main', ['request_id' => 'r-1']);
$run = $actions->runs('deploy.yml')->event('workflow_dispatch')->branch('main')->first(); // the queued run

$fake->fakeFor(ProviderName::Github)->seedWorkflowRun($completed);   // the next poll's state
$actions->cancel($dispatched->runId);                                 // false — already completed

$fake->assertWorkflowDispatched('deploy.yml', 'refs/heads/main', ['request_id' => 'r-1'], 'acme/app');
```

- dispatch() vyžaduje prihlasovacie údaje a vytvorí run vo fronte, ktorý hlási: ďalšie číselné id (na prázdnom fake 1), udalosť workflow\_dispatch, headBranch z refu a headSha zo seedBranch(), inak fake-sha. Po seedDispatchWithoutRunDetails() odpovie bez runId ako GitHub Enterprise Server — run vznikne v oboch prípadoch, takže sa dá otestovať aj náhradné hľadanie.
- runs() vráti naplnené runy od najnovšieho, stránkované s total, a rešpektuje workflow aj každý filter. run($id) vráti naplnený run, inak RuntimeException s názvom seedWorkflowRun(); seedWorkflowRun() run podľa id vloží alebo prepíše, takže ním pripravíte stav pre ďalšie sledovanie.
- jobs() vráti seedWorkflowJobs($runId, …) — predvolene posledný pokus, po allAttempts() všetky, po attempt($n) jeden.
- cancel() vyžaduje prihlasovacie údaje a vráti false, keď je naplnený run dokončený, inak true. Seedy zostanú bez zmeny: GitHub ruší asynchrónne, takže ďalší stav si test pripraví sám.
- activity() stránkuje seedActivity() v poradí naplnenia, filtrované podľa refu; kurzor, ktorý fake nikdy nevydal, vyhodí InvalidArgumentException. compare() bez seedu vráti Identical bez commitov.
- Fake GitLab alebo Bitbucket odmietne každé volanie Actions aj activity(), rovnako ako produkcia.

## Toky GitHub App

S nastavenými fiktívnymi kľúčmi aplikácie sa Git::githubApp() prihlási ako aplikácia a Git::github() ako inštalácia, takže celý tok inštalácie a overenia prebehne bez HTTP:

```php
config([
    'git.providers.github.app.id' => '123',
    'git.providers.github.app.private_key' => 'test-key',
    'git.providers.github.app.installation_id' => '456',
]);

$fake = Git::fake();
$fake->fakeFor(ProviderName::Github)->seedInstallation($installation)->seedRepositories([$repositoryDto]);

Git::githubApp()->installations()->forOrganization('acme-inc');
Git::github()->installationRepositories();

Git::assertSent(ProviderName::Github, 'organizationInstallation');
```

installUrl() vyžaduje app.slug rovnako ako skutočný driver — bez neho vyhodí missingAppConfig() — a slug zakóduje rovnakým spôsobom.

## Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

[Ďalšie spôsoby podpory vrátane kryptomien](https://roundly-consulting.com/sk/podporte-nas.md)

Odoslaním daru súhlasíte s našimi [podmienkami prijímania darov](https://roundly-consulting.com/sk/podmienky-darov.md).

[Podporte našu open-source prácu (otvorí sa v novej karte)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Pridajte sa k nám na Patreone (otvorí sa v novej karte)](https://www.patreon.com/cw/roundly)

## Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.

[Ponuka do 48 hodín](https://roundly-consulting.com/sk/kontakt.md) [Prezrieť všetky balíky](https://roundly-consulting.com/sk/open-source/navody/git-for-laravel.md)
