---
title: "Testovanie — Coupons for Laravel | Roundly"
description: "Coupons::fake() zaznamená vytvorenia, uplatnenia, odmietnutia, odvolania aj čistenia bez zápisu do databázy — plus stavy factory pre databázové testy."
url: https://roundly-consulting.com/sk/open-source/navody/coupons-for-laravel/testovanie
language: sk
---

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

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

# Testovanie

Coupons::fake() nahradí manažéra — pre fasádu aj pre každý injektovaný CouponManager — triedou CouponsFake, záznamníkom, ktorý nič nezapisuje: žiadne riadky ani udalosti. Vráti ho pre asercie. Cez manažéra idú aj model Coupon, trait HasCoupons, pravidlo Redeemable a oba Artisan príkazy, takže sa zaznamenajú aj uplatnenia cez $coupon->redeemBy() a $user->redeemCoupon():

```php
use RoundlyConsulting\Coupons\Enums\DiscountType;
use RoundlyConsulting\Coupons\Facades\Coupons;
use RoundlyConsulting\Money\Money;

$fake = Coupons::fake();

Coupons::generate(DiscountType::Fixed, 500, 'TEN', currency: 'USD');
$result = Coupons::code('TEN')->redeem(Money::ofMinor(5000, 'USD'), $user);
$result->total;                                                   // 45.00 USD — the real discount math, no row written
$user->redeemCoupon('WELCOME', Money::ofMinor(2000, 'USD'));      // recorded too

$fake->assertCreated(fn ($coupon) => $coupon->code === 'TEN');
$fake->assertRedeemed('TEN', fn ($result) => $result->redeemer?->is($user));
$fake->assertRedeemed('WELCOME');
$fake->assertNothingRevoked();
```

## Všetky asercie

```php
$fake->assertCreated();                                             // or a callback: fn (Coupon $c) => …
$fake->assertNothingCreated();
$fake->assertRedeemed('SUMMER');                                    // by code
$fake->assertRedeemed('SUMMER', fn ($result) => /* ... */ true);    // by code + callback
$fake->assertRedeemed(callback: fn ($result) => /* ... */ true);    // by callback only
$fake->assertNotRedeemed('OTHER');
$fake->assertNothingRedeemed();
$fake->assertRedemptionFailed('OLD', RedemptionFailureReason::Expired); // reason optional; a string works too
$fake->assertRevoked('SUMMER');                                     // code optional
$fake->assertExpiredAll();
$fake->assertNothingRevoked();                                      // no revoke() and no expireAll()
$fake->assertPruned(days: 30, force: false);                        // both optional
$fake->assertNothingPruned();
```

| Assercia | Prejde, keď |
| --- | --- |
| `assertCreated(?callable $callback = null)` | Vznikol akýkoľvek kupón — alebo taký, ktorý callback prijme. |
| `assertNothingCreated()` | Nevznikol žiadny kupón. |
| `assertRedeemed(?string $code = null, ?callable $callback = null)` | Akékoľvek úspešné uplatnenie alebo také, ktoré vyhovie kódu a/alebo callbacku. Len callback: assertRedeemed(callback: fn ($result) => …). |
| `assertNotRedeemed(string $code)` | Žiadne úspešné uplatnenie daného kódu. |
| `assertNothingRedeemed()` | Žiadne úspešné uplatnenia. |
| `assertRedemptionFailed(string $code, RedemptionFailureReason\|string\|null $reason = null)` | Odmietnutý pokus pre daný kód — voliteľne s daným dôvodom ako enum alebo jeho hodnota. |
| `assertRevoked(?string $code = null)` | Odvolaný bol akýkoľvek kupón — alebo ten s daným kódom — cez revoke() či code()->revoke(). |
| `assertExpiredAll()` | Zavolalo sa expireAll(). |
| `assertNothingRevoked()` | Nezavolalo sa revoke() ani expireAll(). |
| `assertPruned(?int $days = null, ?bool $force = null)` | Zavolalo sa prune() — voliteľne s daným oknom a/alebo režimom. |
| `assertNothingPruned()` | Nezavolalo sa prune(). |

## Ako sa fake správa

- generate(), create() a createQuietly() vracajú neuložené inštancie triedy z coupons.model — s kódom FAKE-1, FAKE-2, …, ak kód nezadáte —, zaznamenajú ich a nespúšťajú žiadne udalosti. Odmietnu rovnaké neplatné definície ako skutočné metódy (InvalidCouponDefinition) a explicitný kód, ktorý už má kupón vytvorený na fake alebo nezmazaný riadok v databáze, vyhodí CouponCodeTaken, rovnako ako v produkcii.
- Čítanie najprv prehľadá kupóny vytvorené na fake, potom databázu: find(), findOrFail() a exists(). Kódy sa porovnávajú bez ohľadu na veľkosť písmen, rovnako ako v produkcii. redeemable() vracia vždy prázdny builder nad triedou z coupons.model.
- Neznámy kód sa správa ako nový kupón triedy z coupons.model bez obmedzení s nulovou hodnotou: check() vráti null, preview() nulu a redeem() zaznamená úspech — tok „overiť a uplatniť“ tak funguje bez prípravy dát.
- Kupóny vytvorené na fake sa tiež považujú za aktívne: kupón v pamäti bez activated\_at aj expires\_at sa posudzuje ako aktivovaný v danej chvíli, takže limity použití naďalej platia. Riadok v databáze prejde skutočnými kontrolami: pripravený kupón, ktorý nikto neaktivoval, sa odmietne ako Expired, presne ako v produkcii.
- Použitia sa spotrebúvajú ako v produkcii: každý zaznamenaný úspech sa ráta ako jedno použitie kupónu a, kým je coupons.redeemer.track zapnuté, aj ako jedno použitie daným zákazníkom. Druhé uplatnenie jednorazového kupónu sa zaznamená ako neúspech s AtMaxUsage, druhé uplatnenie kupónu „jeden na zákazníka“ tým istým zákazníkom s AlreadyRedeemed — a check() vráti to isté.
- redeem() nikdy nevyhodí výnimku. Úspech vráti zľavu a celkovú sumu, ktoré by vypočítalo skutočné uplatnenie — 20 % kupón na 50.00 EUR dá discount 10.00 a total 40.00; odmietnutie vráti nulovú zľavu a plnú cenu, zaznamená sa len ako neúspech a nikdy sa neráta ako uplatnenie.
- revoke() ukončí platnosť kupónu len v pamäti, bez uloženia, a zaznamená ho; expireAll() zaznamená volanie a ukončí platnosť zodpovedajúcich platných kupónov vytvorených na fake; prune() zaznamená svoje argumenty a vráti 0.

Ak chcete otestovať odmietnutie, použite kupón, ktorý by bol odmietnutý — vytvorte ho na fake cez Coupons::generate(), ako riadok v databáze, alebo odovzdajte model ako tu:

```php
use RoundlyConsulting\Coupons\Enums\RedemptionFailureReason;
use RoundlyConsulting\Coupons\Facades\Coupons;
use RoundlyConsulting\Coupons\Models\Coupon;
use RoundlyConsulting\Money\Money;

$fake = Coupons::fake();

$expired = Coupon::factory()->percentage(1000)->expired()->make(['code' => 'OLD']);
Coupons::redeem($expired, Money::ofMinor(1000, 'EUR'));   // recorded as a failure, never throws

$fake->assertRedemptionFailed('OLD', RedemptionFailureReason::Expired);  // or 'expired'
$fake->assertNotRedeemed('OLD');
```

Artisan príkazy tiež injektujú manažéra, takže ich fake zaznamená:

```php
use RoundlyConsulting\Coupons\Facades\Coupons;

$fake = Coupons::fake();

$this->artisan('coupons:expire', ['--code' => 'SUMMER']);
$this->artisan('coupons:prune', ['--days' => 90, '--force' => true]);

$fake->assertExpiredAll();
$fake->assertPruned(days: 90, force: true);
```

## Factory

Coupon::factory() obsahuje stavy pre každý typ kupónu; k dispozícii je aj CouponRedemption::factory():

```php
use RoundlyConsulting\Coupons\Models\Coupon;
use RoundlyConsulting\Money\Money;

Coupon::factory()->active()->fixed(500, 'EUR')->withMinimumSpend(Money::ofMinor(2000, 'EUR'))->create();
Coupon::factory()->active()->percentage(2500)->create(['code' => 'QUARTER']);
Coupon::factory()->active()->cappedPercentage(5000, Money::ofMinor(300, 'EUR'))->create();
Coupon::factory()->freeShipping()->expired()->create();
```

- active() / expired() — aktivovaný alebo expirovaný pred hodinou.
- fixed(int $value = 100, ?string $currency = null) — uzamknutý na menu, predvolene coupons.default\_currency.
- percentage(int $basisPoints = 1000) — neuzamknutý.
- freeShipping().
- cappedPercentage(int $basisPoints = 2500, ?Money $maxDiscount = null) — strop je predvolene 500 najmenších jednotiek predvolenej meny.
- withMinimumSpend(Money $minimumSpend) a forCurrency(string $currency) — oba uzamknú menu.

## Proti skutočnej databáze

Pri end-to-end testoch publikujte migrácie do aplikácie, aby RefreshDatabase vytvoril obe tabuľky, a potom testujte cez skutočný tok:

```php
use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Coupons\Events\CouponExhausted;
use RoundlyConsulting\Coupons\Exceptions\CouponAtMaxUsage;
use RoundlyConsulting\Coupons\Facades\Coupons;
use RoundlyConsulting\Coupons\Models\Coupon;
use RoundlyConsulting\Money\Money;

it('sells out after the last use', function () {
    Event::fake([CouponExhausted::class]);

    Coupon::factory()->active()->fixed(500, 'EUR')->create(['code' => 'ONCE', 'max_usage' => 1]);

    $result = Coupons::redeem('ONCE', Money::ofMinor(5000, 'EUR'));
    expect($result->total->minor())->toBe('4500');

    expect(fn () => Coupons::redeem('ONCE', Money::ofMinor(5000, 'EUR')))
        ->toThrow(CouponAtMaxUsage::class);

    Event::assertDispatchedTimes(CouponExhausted::class, 1);
});
```

Vlastné testy balíka spustíte príkazom:

```bash
composer test
```

## 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/coupons-for-laravel.md)
