Testes unitários com JUnit
Escreva testes unitários rápidos e confiáveis com JUnit 4. Use @Test, @Before, @After e asserções; teste LiveData com InstantTaskExecutorRule e corrotinas com runTest.
Testes unitários com JUnit é uma aula grátis de Android Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Android Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Android Academy inclui 4 aulas no total.
Por que escrever testes?
Testes não são um luxo — são a sua rede de segurança:
- Detectam erros antes que os usuários os encontrem
- Permitem refatorar com confiança (se os testes passam, nada foi quebrado)
- Documentam o comportamento esperado
- Evitam regressões ao adicionar funcionalidades
Código bem testado também tende a ser código com um design melhor — se for difícil testá-lo, provavelmente o design está muito acoplado.
Tipos de testes do Android
Duas categorias:
- Testes unitários (pasta
test/) — executados na JVM, sem necessidade de dispositivo. São rápidos. Testam lógica simples em Kotlin/Java. - Testes instrumentados (pasta
androidTest/) — executados em um dispositivo ou emulador. São mais lentos. Testam código específico do Android (banco de dados Room, interface).
Dê preferência aos testes unitários para a lógica de negócio. Use testes instrumentados somente quando precisar interagir com APIs do Android.
Configuração do JUnit 4
O JUnit 4 vem incluído por padrão nos projetos Android. Adicione estes itens 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
}Seu primeiro teste com JUnit
Crie uma classe em src/test/java/ e anote os métodos de teste com @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 e @After
Use anotações de ciclo de vida para configurar e limpar o estado antes e depois de cada teste:
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)
}
}Asserções comuns
O JUnit fornece métodos de asserção em 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 = "")
}Testando um ViewModel
Para testar LiveData, adicione InstantTaskExecutorRule para que o LiveData publique os valores 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)
}
}Testando corrotinas
Use TestCoroutineDispatcher / StandardTestDispatcher para controlar a execução de corrotinas nos testes:
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 ou Mock
Duas estratégias para substituir dependências reais nos testes:
- Fake — uma implementação funcional criada para testes (por exemplo, uma lista em memória no lugar de um banco de dados real). É fácil de escrever, legível e não exige uma biblioteca.
- Mock — um stub gerado automaticamente que registra chamadas e permite verificar interações (Mockito, MockK). É mais poderoso, mas pode se tornar frágil quando usado em excesso.
Dê preferência a Fakes em casos simples; use Mocks quando precisar verificar chamadas de métodos.
Escrevendo um Fake
Um Fake implementa a mesma interface que a classe real, mas usa armazenamento em memória:
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() }
}Convenção para nomear testes
Bons nomes de testes descrevem o que está sendo testado e o resultado esperado. Use nomes de funções entre crases em Kotlin para obter descrições legíveis:
`getUsers returns empty list when no users exist``login throws exception when password is blank``add returns correct sum for negative numbers`
Padrão: `subject does X when Y`
Verificação rápida
Qual é a finalidade de @Before em uma classe de teste do JUnit?
Recapitulação: testes unitários com JUnit
Aplicativos confiáveis são aplicativos testados:
- Os testes unitários ficam em
src/test/e são executados na JVM — são rápidos - Use
@Test,assertEquals,assertTrueeassertThrows @Before/@Afterpara configurar e limpar o estadoInstantTaskExecutorRulepara testar LiveData de forma síncronarunTest+StandardTestDispatcherpara testar corrotinas- Dê preferência a Fakes em vez de Mocks para substituições simples
A seguir: simulação com Mockito para verificar interações.
Perguntas Frequentes
A aula “Testes unitários com JUnit” é grátis?
Sim — o texto completo de “Testes unitários com JUnit” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Android Academy, atualize para CoddyKit PRO. O curso de Android Academy inclui 4 aulas no total.
O que vou aprender em “Testes unitários com JUnit”?
Escreva testes unitários rápidos e confiáveis com JUnit 4. Use @Test, @Before, @After e asserções; teste LiveData com InstantTaskExecutorRule e corrotinas com runTest. Você pratica Android Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Android Academy?
Nenhuma experiência prévia é necessária. Android Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “Testes unitários com JUnit”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Android Academy?
Sim. Cada aula de Android Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Testes unitários com JUnit
- Simulação com Mockito
- Testes de interface com Espresso
- Depuração e criação de perfis