# Kotlin Testing — Referencia Avanzada

## Robolectric — Tests Android sin Emulador

```kotlin
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [34])
class FacturasNotificationTest {

    @Test
    fun `notificacion se crea con titulo correcto`() {
        val context = ApplicationProvider.getApplicationContext<Context>()
        val builder = FacturasNotificationBuilder(context)

        val notification = builder.construir("Factura F-001 procesada")

        val extras = notification.extras
        assertEquals("Facturas", extras.getString(Notification.EXTRA_TITLE))
        assertEquals("Factura F-001 procesada",
            extras.getString(Notification.EXTRA_TEXT))
    }
}
```

---

## Ktor Test Client

```kotlin
class FacturasApiTest {

    @Test
    fun `POST facturas retorna 201 con datos validos`() = testApplication {
        application { configurarRouting() }

        val client = createClient {
            install(ContentNegotiation) { json() }
        }

        val response = client.post("/api/v1/facturas") {
            contentType(ContentType.Application.Json)
            setBody(CrearFacturaRequest(folio = "F-001", empresaId = "empresa-1"))
        }

        assertEquals(HttpStatusCode.Created, response.status)
        val dto = response.body<FacturaDto>()
        assertEquals("F-001", dto.folio)
    }
}
```

---

## Fake vs Mock — cuándo usar cada uno

```kotlin
// Fake — implementación en memoria para tests de integración
class FakeFacturasRepository : IFacturasRepository {
    private val facturas = mutableListOf<Factura>()
    private val _flow = MutableStateFlow(facturas.toList())

    override fun observarFacturas(empresaId: String): StateFlow<List<Factura>> =
        _flow.map { list -> list.filter { it.empresaId == empresaId } }
            .stateIn(CoroutineScope(UnconfinedTestDispatcher()), Eagerly, emptyList())

    override suspend fun guardar(factura: Factura) {
        facturas.add(factura)
        _flow.value = facturas.toList()
    }
}

// Mock (MockK) — cuando el test verifica interacciones específicas, no estado
// Usar mockk cuando importa CÓMO se llama algo, no solo el resultado
```
