Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

[Bug] o var totalDeContas dá resultados diferentes dependendo de como eu faço o teste

Bom dia a todos

Eu tava fazendo a aula, mas como eu já fiz uns cursos de java, preferi fazer a execucão através do Junit ao invés de fazer em um arquivo Kotlin no fun main(). Ao fazer os testes, criei 3 objetos do tipo conta:

    private val alex = ContaPoupanca(Cliente("Alex", "1223456789",
        1234, Endereco()), 1234, BigDecimal(55.60))
    private val luiz = ContaPoupanca(numeroDaConta = 1235, saldo =
    BigDecimal(10.9),nomeTitular = Cliente("Luiz","76534587645",6789, Endereco()))
    private val salario = ContaSalario(Cliente("Mariana","23454367890"
        ,5678, Endereco()),1234, BigDecimal(50))

e fiz os testes para verificar se o totalDeContas estava correto:

    @Test
    fun testaContadorDoNumeroDeContas(){
        assertEquals(3,Conta.totalDeContas)
    }

Mas uma coisa muito inesperada aconteceu, se eu fizer o teste só nesse método dá certo, mas se eu rodar todos os testes do arquivo, por algum motivo dá 12, com essa mensagem:

org.opentest4j.AssertionFailedError: 
Expected :3
Actual   :12
<Click to see difference>

Eu sei que fugi um pouco da matéria, mas isso é tão inesperado e não faço a menor ideia porque isso pode ter ocorrido. Queria saber que está acontecendo. Código completo dos testes:


import br.com.alura.dominio.cliente.Cliente
import br.com.alura.dominio.cliente.dados_extras.Endereco
import br.com.alura.exceptions.excecao.SaldoInsuficienteException
import org.hamcrest.CoreMatchers
import org.hamcrest.MatcherAssert
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.test.system.CapturedOutput
import org.springframework.boot.test.system.OutputCaptureExtension
import java.math.BigDecimal
import java.math.MathContext
@ExtendWith(OutputCaptureExtension::class)
class ContaTest{
    private val alex = ContaPoupanca(Cliente("Alex", "1223456789",
        1234, Endereco()), 1234, BigDecimal(55.60))
    private val luiz = ContaPoupanca(numeroDaConta = 1235, saldo =
    BigDecimal(10.9),nomeTitular = Cliente("Luiz","76534587645",6789, Endereco()))
    private val salario = ContaSalario(Cliente("Mariana","23454367890"
        ,5678, Endereco()),1234, BigDecimal(50))
    private fun getValor(numero:BigDecimal):BigDecimal{
        return numero.round(MathContext.DECIMAL64).setScale(2)
    }
    @Test
    fun testaAlteracaoDeAtributoDaConta(){
        assertEquals(getValor(BigDecimal(55.60)),alex.saldoDaConta)
        alex.depositaDinheiro(BigDecimal(50.0))
        assertEquals(getValor(BigDecimal(105.6)),alex.saldoDaConta)
    }
    @Test
    fun testaSaqueDeDinheiro(){
        alex.sacaDinheiro(BigDecimal(20.0))
        assertEquals(getValor(BigDecimal(35.6)),alex.saldoDaConta)
        assertThrows(SaldoInsuficienteException::class.java){
            alex.sacaDinheiro(BigDecimal(80.0))
        }
    }
    @Test
    fun testaTransferenciaDeDinheiro(){
        alex.transfereDinheiro(BigDecimal(20.0),luiz)
        assertEquals(getValor(BigDecimal(35.6)),alex.saldoDaConta)
        assertEquals(getValor(BigDecimal(30.9)),luiz.saldoDaConta)
        assertThrows(SaldoInsuficienteException::class.java){
            luiz.transfereDinheiro(BigDecimal(50.0),alex)
        }
    }
    @Test
    fun testaContaSalarioPodeReceberTransferencia(){
        alex.transfereDinheiro(BigDecimal(20.0),salario)
        assertEquals(getValor(BigDecimal(35.6)),alex.saldoDaConta)
        assertEquals(getValor(BigDecimal(70)),salario.saldoDaConta)
    }
    @Test
    fun testaComposicaoComCliente(output:CapturedOutput){
        alex.nomeTitular.mudaSenha(1234,56789)
        MatcherAssert.assertThat(output.all, CoreMatchers.containsString("senha alterada com sucesso"))
    }
    @Test
    fun testaToString(){
        assertEquals("Conta(nomeTitular='Alex', CPF='1223456789' numeroDaConta=1234)",alex.toString())
    }
    @Test
    fun testaContadorDoNumeroDeContas(){
        assertEquals(3,Conta.totalDeContas)
    }
}

O código da conta vou deixar nos comentários para não passar de 5000 mil caractertes

2 respostas

Código da conta principal

import br.com.alura.exceptions.excecao.SaldoInsuficienteException
import br.com.alura.dominio.cliente.Cliente
import java.math.BigDecimal
import java.math.MathContext

abstract class Conta (
    val nomeTitular: Cliente,
    val numeroDaConta: Int, saldo: BigDecimal,
){
    var saldoDaConta: BigDecimal = saldo
        get(){return field.round(MathContext.DECIMAL64).setScale(2)}
        protected set
    init {
        totalDeContas++
    }
    fun depositaDinheiro(deposita:BigDecimal){
        saldoDaConta += deposita
    }
    open fun sacaDinheiro(saca:BigDecimal){
        if (saca > saldoDaConta){
            throw SaldoInsuficienteException()
        }
        saldoDaConta -= saca
    }

    override fun toString(): String {
        return "Conta(nomeTitular='${nomeTitular.nome}', CPF='${nomeTitular.cpf}' numeroDaConta=$numeroDaConta)"
    }
    companion object{
        var totalDeContas:Int = 0
            private set
    }
}

Conta Corrente:

import br.com.alura.exceptions.excecao.SaldoInsuficienteException
import br.com.alura.dominio.cliente.Cliente
import br.com.alura.dominio.conta.transferencia.Transferencia
import java.math.BigDecimal
import java.math.MathContext

class ContaCorrente(
    nomeTitular: Cliente,
    numeroDaConta: Int,
    saldo: BigDecimal
) :
    Conta(nomeTitular, numeroDaConta, saldo), Transferencia {
    override fun sacaDinheiro(saca: BigDecimal) {
        val sacaComTaxa = saca.add(BigDecimal(0.1))
        if (sacaComTaxa > saldoDaConta){
            throw SaldoInsuficienteException()
        }
        this.saldoDaConta -= sacaComTaxa.round(MathContext.DECIMAL64).setScale(2)
    }
    override fun transfereDinheiro(valor:BigDecimal,conta: Conta){
        if (valor > saldoDaConta){
            throw SaldoInsuficienteException()
        }
        saldoDaConta -= valor
        conta.depositaDinheiro(valor)
    }
}

Conta poupanca:

import br.com.alura.dominio.cliente.Cliente
import br.com.alura.dominio.conta.transferencia.Transferencia
import java.math.BigDecimal

class ContaPoupanca(
    nomeTitular: Cliente,
    numeroDaConta: Int,
    saldo: BigDecimal
) :
    Conta(nomeTitular, numeroDaConta, saldo), Transferencia {
    override fun transfereDinheiro(valor: BigDecimal, conta: Conta) {
        this.sacaDinheiro(valor)
        conta.depositaDinheiro(valor)
    }
}

Conta salário:

import br.com.alura.dominio.cliente.Cliente
import java.math.BigDecimal

class ContaSalario(
    nomeTitular: Cliente,
    numeroDaConta: Int,
    saldo: BigDecimal
) :
    Conta(nomeTitular, numeroDaConta, saldo)
solução!

Olá, Murilo! Tudo bem?

Entendi que você está com um problema inesperado ao rodar todos os testes do arquivo no JUnit. Pelo que pude analisar, o problema está relacionado ao fato de que o contador totalDeContas está sendo incrementado várias vezes, resultando em um valor maior do que o esperado.

Uma possível solução para esse problema é utilizar o Companion Object do Kotlin. O Companion Object é um objeto que compartilha seus membros com a classe em que está inserido, permitindo que eles sejam acessados como se fossem membros da própria classe.

No seu caso, você pode criar um Companion Object dentro da classe Conta e mover o contador totalDeContas para dentro dele. Assim, o contador será compartilhado por todas as instâncias da classe Conta e não será incrementado várias vezes durante a execução dos testes.

Veja como ficaria o código:

class Conta {
    // ...

    companion object {
        var totalDeContas = 0
    }
}

Dessa forma, você pode acessar o contador totalDeContas utilizando Conta.totalDeContas em qualquer lugar do seu código, incluindo os testes. O valor do contador será mantido corretamente, mesmo quando você rodar todos os testes do arquivo.

Espero que essa solução ajude a resolver o seu problema! Se tiver mais alguma dúvida, é só me dizer. Espero ter ajudado e bons estudos!