kassensichv.mock

Zurück zur KassenSichV-Übersicht

Vollständiger TSE-Mock-Provider ohne physische Hardware. Für Unit-Tests, CI/CD-Pipelines und Bondrucktests. Erzeugt deterministische SHA-256-basierte Testsignaturen (kein echtes ECDSA). Keine externen Abhängigkeiten.

Import

import kassensichv.types;
import kassensichv.mock;
import kassensichv.manager;

Erzeugen

pub fn TseMockNew(): int64;
// Gibt TseManager-Handle zurück (allokiert)
// Kein Konfigurationsparameter nötig — Mock akzeptiert alles
// Mit TseManagerFree() freigeben

var mgr: int64 := TseMockNew();
// Direkt verwendbar — keine Initialize()-Konfiguration nötig

Fehlersimulation

Der Mock kann verschiedene Fehlersituationen simulieren, um die Fehlerbehandlung der Kassensoftware zu testen:

// Verbindungsfehler simulieren (TseProcessBeleg gibt success=0, code=503)
pub fn TseMockSetSimulateError(mgr: int64, on: int64): void;

// Timeout simulieren (TseProcessBeleg gibt success=0, code=408)
pub fn TseMockSetSimulateTimeout(mgr: int64, on: int64): void;

fn TestVerbindungsfehler(): void {
    var mgr: int64 := TseMockNew();
    TseMockSetSimulateError(mgr, 1);    // Fehler einschalten

    var beleg: BelegDaten;
    beleg.prozessTyp := PROZESSTYP_KASSENBELEG;
    var sig: int64   := TseProcessBeleg(mgr, addr beleg);

    var s: SigErgebnis := (sig as *SigErgebnis)^;
    // s.success = 0, s.errorMsg = "Simulierter Verbindungsfehler..."
    SigErgebnisFree(sig);

    TseMockSetSimulateError(mgr, 0);    // Fehler ausschalten
    TseManagerFree(mgr);
}

Testzustandsabfrage

// Aktueller Transaktionszähler (monoton steigend ab 0)
pub fn TseMockGetZaehler(mgr: int64): int64;

// TSE-Seriennummer des Mocks
pub fn TseMockGetSerial(mgr: int64): int64;   // pchar, allokiert

Der Mock-Zähler startet bei 0 und steigt mit jedem erfolgreichen TseProcessBeleg / TseCloseBeleg um 1. Er kann in Tests für Assertions verwendet werden:

fn TestZaehlerMonoton(): void {
    var mgr: int64 := TseMockNew();

    // Erster Bon: Zähler wird 1
    var b1: BelegDaten; b1.prozessTyp := PROZESSTYP_KASSENBELEG;
    var sig1: int64 := TseProcessBeleg(mgr, addr b1);
    SigErgebnisFree(sig1);

    // Zweiter Bon: Zähler wird 2
    var b2: BelegDaten; b2.prozessTyp := PROZESSTYP_KASSENBELEG;
    var sig2: int64 := TseProcessBeleg(mgr, addr b2);
    var s2: SigErgebnis := (sig2 as *SigErgebnis)^;

    // s2.sigZaehler == 2 (immer höher als vorheriger)
    SigErgebnisFree(sig2);

    TseManagerFree(mgr);
}

Signaturwert-Erzeugung

Der Mock erzeugt Signaturen als SHA-256-Hash über (TransId + Zeitstempel-Millisekunden), Base64-kodiert. Das Ergebnis ist deterministisch für gleiche Eingaben, aber kryptografisch unsicher — nur für Tests geeignet.

Echte TSEs verwenden ECDSA/SHA-256 mit einem hardwaregeschützten Schlüssel (nicht aus dem Gerät extrahierbar).

Mock-Seriennummer

Der Mock verwendet immer die feste Seriennummer:

MOCK-TSE-0000000000000001

In Tests, die die TSE-Seriennummer auf dem Bon prüfen, diesen Wert als Referenz verwenden.

ExportAuditData

TseExportAuditData mit dem Mock erstellt eine leere mock_audit.tar im Zielverzeichnis. Die Datei existiert, hat aber keinen Inhalt (Mock-Daten). Nützlich, um den Export-Workflow (Verzeichnis schreibbar, index.json vorhanden) ohne echte TSE zu testen.

Vollständiges Test-Beispiel

import kassensichv.types;
import kassensichv.mock;
import kassensichv.manager;

fn TestKomplettprozess(): void {
    var mgr: int64 := TseMockNew();

    // --- Einfacher Bon ---
    var beleg: BelegDaten;
    beleg.prozessTyp   := PROZESSTYP_KASSENBELEG;
    beleg.kassenNr     := "KASSE-001"c;
    beleg.prozessDaten := "Kaffee;2.50_0.00_0.00_0.00_0.00"c;
    beleg.umsatz       := 250;

    var sig: int64 := TseProcessBeleg(mgr, addr beleg);
    var s: SigErgebnis := (sig as *SigErgebnis)^;

    // Prüfungen
    // s.success  == 1
    // s.sigZaehler == 1
    // s.qrCode beginnt mit "V0;MOCK-TSE-"

    SigErgebnisFree(sig);

    // --- Fehlersimulation ---
    TseMockSetSimulateTimeout(mgr, 1);
    var beleg2: BelegDaten; beleg2.prozessTyp := PROZESSTYP_KASSENBELEG;
    var sig2: int64 := TseProcessBeleg(mgr, addr beleg2);
    var s2: SigErgebnis := (sig2 as *SigErgebnis)^;

    // s2.success == 0
    // s2.errorMsg enthält "Timeout"
    SigErgebnisFree(sig2);
    TseMockSetSimulateTimeout(mgr, 0);

    TseManagerFree(mgr);
}


Letzte Aktualisierung: 2026-06-12