Skip to content

NFR-2.2: BLE mocking for CI test environments #31

Description

@itsniper

Goal

Ensure all BLE interactions in tests use mocking or simulation so swift test runs reliably in CI without physical Bluetooth hardware or user authorization prompts.

Context

Parent requirement NFR-2.2 from #9:

Use mocking or simulation for BLE peripherals to facilitate testing in CI environments.

The project already has foundational mock infrastructure via the three-target SPM trick documented in AGENTS.md:

  • ReliaBLE — production target; real CoreBluetooth.
  • ReliaBLEMock — same sources with CBCentralManagerFactory.swift excluded; CoreBluetoothMockAliases.swift rebinds CBCentralManager, CBPeripheral, etc. to Nordic Semi's CBM* types.
  • ReliaBLETests — depends on ReliaBLEMock, not ReliaBLE.

BluetoothActor instantiates the central via CBCentralManagerFactory.instance(..., forceMock: true). The production factory ignores forceMock; the mock factory honors it — this parameter is load-bearing and must not be removed.

Current tests exercise the mock target but do not yet drive simulated peripherals or central-manager state changes. Several NFR-2.1 scenarios (scanning, discovery events, connection success, authorization flows) depend on this harness.

Deliverable

  1. Document the mock testing pattern in a brief comment block or test helper (e.g. MockBLEHarness / BluetoothTestSupport) that shows how to:
    • Obtain the mock CBMCentralManager (or equivalent) from the test context.
    • Simulate central-manager state changes (powered on/off, unauthorized, etc.).
    • Simulate peripheral discovery (simulatePeripheral or delegate callback injection).
    • Simulate connection events.
  2. Refactor or extend tests so every test that touches BLE goes through the mock stack — no test should require a real radio or iOS Bluetooth permission dialog.
  3. Verify CI readiness — confirm swift test passes in a headless macOS environment (GitHub Actions runner) with no Bluetooth adapter dependency. Coordinate with NFR 11: Continuous Integration (GitHub Actions) #21 (NFR 11 — CI) so the test job uses the mock target exclusively.
  4. Preserve the three-target constraint — library code must continue to call CBCentralManagerFactory.instance(...), never CBCentralManager(...) directly. Do not move mock-only logic into Sources/ReliaBLE/.

Mock capabilities to leverage

  • Nordic IOS-CoreBluetooth-MockCBMCentralManager, CBMPeripheral, delegate simulation APIs.
  • Existing aliases in Sources/ReliaBLEMock/CoreBluetoothMockAliases.swift.
  • @testable import ReliaBLEMock for access to internal BluetoothActor in tests.

Acceptance criteria

  • swift test completes successfully on a macOS CI runner with no Bluetooth hardware.
  • At least one integration-style test drives a full mock flow: central powers on → scan discovers a simulated peripheral → discoveredPeripherals / peripheralDiscoveries emit expected values.
  • No test imports or links against the production ReliaBLE target.
  • forceMock: true remains in BluetoothActor.setupCentralManager() (or equivalent).
  • A reusable test helper exists so NFR-2.1 tests can add scenarios without duplicating mock setup boilerplate.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions