Testing
Because contracts are runtime values, testing needs no Proxy tricks and no native toolchain. Both sides fake cleanly.
TypeScript: typed mocks
Section titled “TypeScript: typed mocks”mockBridge produces a fully-typed mock from a contract — you implement only the members the
test touches.
import { mockBridge } from '@malopezr7/bridgekit/test';
const mock = mockBridge(AppHost, { isLoggedIn: async () => true,});TypeScript: the loopback transport
Section titled “TypeScript: the loopback transport”createTestBridge() gives you an isolated registry wired to an in-memory loopback
transport — JS provides and JS consumes, with no native side. Feature logic, including
streams and state, runs in plain Jest.
import { createTestBridge } from '@malopezr7/bridgekit/test';
const { bridgekit } = createTestBridge();
bridgekit.provide(AppHost, { isLoggedIn: async () => true });const app = bridgekit.bridge(AppHost);
expect(await app.isLoggedIn()).toBe(true);Kotlin: fake the generated interface
Section titled “Kotlin: fake the generated interface”Generated provider/client interfaces are plain Kotlin interfaces — fake them directly, no mocking framework required.
val fake = object : AppHost { override suspend fun isLoggedIn(): Boolean = true override suspend fun saveFile(params: SaveFileParams) = SaveFileResult.SUCCESS override fun showLogin() {} override fun notifications(): Flow<String> = flowOf("123456") override val connectivity = MutableStateFlow(Connectivity(online = true))}Drive the unit under test directly against that fake. BridgeKit’s own constructor is
internal, so there is no public way to build an isolated instance for a test — the shared
BridgeKit.default is the only instance a consumer app can reach. Test your provider logic
against the interface, not through the runtime.
Swift: fake the generated protocol
Section titled “Swift: fake the generated protocol”The generated Swift provider is a plain protocol (AnyObject-bound, nothing BridgeKit-specific
in the signatures). Conform a test double to it and inject that — no runtime, no Nitro, no
simulator needed for the provider’s own logic.
final class FakeAppHost: AppHost { func isLoggedIn() throws -> Bool { true } func saveFile(_ params: SaveFileParams) async throws -> String { "success" } func closeFeature() {} func showWebpage(_ params: ShowWebpageParams) {} // ...implement only the members the test exercises}
// Drive the unit under test directly against the fake.let host: any AppHost = FakeAppHost()XCTAssertTrue(try host.isLoggedIn())The JS consumer of that same contract is still tested in plain Jest with the loopback transport
(createTestBridge / mockBridge above) — so both ends are covered without a device in the loop.
Why there are no parity tests
Section titled “Why there are no parity tests”You don’t need to test that the two sides agree on the wire format. The single source of
truth (one contract) plus the contract hash guarantee it — drift surfaces as a build
failure (--check) or a structured runtime warning, not as a class of tests you maintain by
hand. Codec round-trip tests can be generated alongside the Kotlin.