0Pricing
Android Academy · Lección

Pruebas unitarias con JUnit

Escriba pruebas unitarias rápidas y fiables con JUnit 4. Use @Test, @Before, @After y aserciones; pruebe LiveData con InstantTaskExecutorRule y corrutinas con runTest.

Pruebas unitarias con JUnit es una lección gratuita de Android Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Android Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Android Academy incluye 4 lecciones en total.

¿Por qué escribir pruebas?

Las pruebas no son un lujo: son su red de seguridad:

  • Detectan errores antes que los usuarios
  • Permiten refactorizar con confianza (si las pruebas pasan, nada se ha roto)
  • Documentan el comportamiento previsto
  • Evitan regresiones al añadir funcionalidades

El código bien probado también suele estar mejor diseñado: si es difícil de probar, probablemente el diseño está demasiado acoplado.

Tipos de pruebas de Android

Dos categorías:

  • Pruebas unitarias (carpeta test/) — se ejecutan en la JVM, sin necesidad de un dispositivo. Son rápidas. Prueban lógica común de Kotlin/Java.
  • Pruebas instrumentadas (carpeta androidTest/) — se ejecutan en un dispositivo o emulador. Son más lentas. Prueban código específico de Android (base de datos Room, interfaz de usuario).

Prefiera las pruebas unitarias para la lógica de negocio. Use pruebas instrumentadas solo cuando deba interactuar con las API de Android.

Configuración de JUnit 4

JUnit 4 se incluye de forma predeterminada en los proyectos de Android. Añada lo siguiente a app/build.gradle:

// app/build.gradle:
dependencies {
    testImplementation 'junit:junit:4.13.2'
    testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3'
    testImplementation 'androidx.arch.core:core-testing:2.2.0'  // for LiveData
}

Su primera prueba de JUnit

Cree una clase en src/test/java/ y anote los métodos de prueba con @Test:

import org.junit.Test
import org.junit.Assert.*

class CalculatorTest {

    private val calc = Calculator()

    @Test
    fun `addition returns correct sum`() {
        val result = calc.add(2, 3)
        assertEquals(5, result)
    }

    @Test
    fun `division by zero throws exception`() {
        assertThrows(ArithmeticException::class.java) {
            calc.divide(10, 0)
        }
    }
}

@Before y @After

Use anotaciones del ciclo de vida para configurar y desmontar el estado alrededor de cada prueba:

class UserRepositoryTest {

    private lateinit var repo: UserRepository
    private lateinit var fakeDao: FakeUserDao

    @Before
    fun setUp() {
        fakeDao = FakeUserDao()          // fresh instance before each test
        repo = UserRepository(fakeDao)
    }

    @After
    fun tearDown() {
        fakeDao.clear()                  // clean up after each test
    }

    @Test
    fun `getUsers returns all users`() {
        fakeDao.insert(User(1, "Alice"))
        fakeDao.insert(User(2, "Bob"))
        assertEquals(2, repo.getUsers().size)
    }
}

Aserciones habituales

JUnit proporciona métodos de aserción en Assert.*:

// Equality:
assertEquals(expected, actual)
assertNotEquals(unexpected, actual)

// Null:
assertNull(value)
assertNotNull(value)

// Boolean:
assertTrue(condition)
assertFalse(condition)

// Same object reference:
assertSame(expected, actual)

// Custom message on failure:
assertEquals("User ID should be 1", 1, user.id)

// Exception:
assertThrows(IllegalArgumentException::class.java) {
    User(id = -1, name = "")
}

Pruebas de un ViewModel

Para probar LiveData, añada InstantTaskExecutorRule para que LiveData publique de forma síncrona:

class UserViewModelTest {

    @get:Rule
    val instantTaskRule = InstantTaskExecutorRule()

    private val fakeRepo = FakeUserRepository()
    private lateinit var viewModel: UserViewModel

    @Before
    fun setUp() {
        viewModel = UserViewModel(fakeRepo)
    }

    @Test
    fun `users are loaded on init`() {
        fakeRepo.usersToReturn = listOf(User(1, "Alice"), User(2, "Bob"))
        viewModel.loadUsers()

        val result = viewModel.users.value
        assertNotNull(result)
        assertEquals(2, result?.size)
    }
}

Pruebas de corrutinas

Use TestCoroutineDispatcher / StandardTestDispatcher para controlar la ejecución de corrutinas en las pruebas:

class SyncWorkerTest {

    @get:Rule
    val instantTaskRule = InstantTaskExecutorRule()

    private val testDispatcher = StandardTestDispatcher()

    @Before
    fun setUp() {
        Dispatchers.setMain(testDispatcher)
    }

    @After
    fun tearDown() {
        Dispatchers.resetMain()
    }

    @Test
    fun `sync completes successfully`() = runTest {
        val repo = FakeRepository()
        val worker = SyncUseCase(repo, testDispatcher)
        val result = worker.run()
        assertTrue(result.isSuccess)
    }
}

Fake frente a Mock

Dos estrategias para reemplazar dependencias reales en las pruebas:

  • Fake — una implementación funcional diseñada para las pruebas (por ejemplo, una lista en memoria en lugar de una base de datos real). Es fácil de escribir y leer, y no requiere ninguna biblioteca.
  • Mock — un objeto simulado generado automáticamente que registra las llamadas y permite verificar las interacciones (Mockito, MockK). Es más potente, pero puede volverse frágil si se usa en exceso.

Prefiera los Fakes para casos sencillos; use Mocks cuando necesite verificar llamadas a métodos.

Cómo escribir un Fake

Un Fake implementa la misma interfaz que la clase real, pero utiliza almacenamiento en memoria:

interface UserDao {
    fun getAll(): List<User>
    fun insert(user: User)
}

class FakeUserDao : UserDao {
    private val storage = mutableListOf<User>()

    override fun getAll(): List<User> = storage.toList()
    override fun insert(user: User) { storage.add(user) }

    fun clear() { storage.clear() }
}

Convención para nombrar pruebas

Los buenos nombres de prueba describen qué se está probando y cuál es el resultado esperado. Use nombres de funciones entre comillas invertidas en Kotlin para obtener descripciones legibles:

  • `getUsers returns empty list when no users exist`
  • `login throws exception when password is blank`
  • `add returns correct sum for negative numbers`

Patrón: `subject does X when Y`

Comprobación rápida

¿Cuál es la finalidad de @Before en una clase de prueba de JUnit?

Repaso: pruebas unitarias con JUnit

Las aplicaciones fiables son aplicaciones probadas:

  • Las pruebas unitarias se colocan en src/test/ y se ejecutan en la JVM; son rápidas
  • Anótelas con @Test y use assertEquals, assertTrue y assertThrows
  • @Before / @After para la configuración y el desmontaje
  • InstantTaskExecutorRule para probar LiveData de forma síncrona
  • runTest + StandardTestDispatcher para probar corrutinas
  • Prefiera los Fakes a los Mocks para sustituciones sencillas

A continuación: simulación con Mockito para verificar interacciones.

Preguntas frecuentes

¿La lección «Pruebas unitarias con JUnit» es gratis?

Sí — el texto completo de «Pruebas unitarias con JUnit» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Android Academy, actualiza a CoddyKit PRO. El curso de Android Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Pruebas unitarias con JUnit»?

Escriba pruebas unitarias rápidas y fiables con JUnit 4. Use @Test, @Before, @After y aserciones; pruebe LiveData con InstantTaskExecutorRule y corrutinas con runTest. Practicas Android Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Android Academy?

No se requiere experiencia previa. Android Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.

¿Cuánto tiempo toma la lección «Pruebas unitarias con JUnit»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Android Academy?

Sí. Cada lección de Android Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Pruebas unitarias con JUnit
  2. Mocking con Mockito
  3. Pruebas de interfaz con Espresso
  4. Depuración y profiling
← Volver a Android Academy