Teste Unitários

Igor Curvelo
4 min readOct 22, 2021

--

Testando 1,2,3 ….

Os testes unitários tem como objetivo testar apenas uma pequena parte de código ou unidade do sistema.

Imagine que temos um método ou função que precisamos testar independente de qualquer parte do sistema que usará essa função.

Pensando assim temos que um teste unitário trabalha com um escopo bem especifico e isolado.
Por conta disso, recursos externos como: APIs, bancos de dados, ou outras classes podem ou devem ser mockadas.

Mocks, são objetos criados para imitar outros objetos reais do sistema.
Onde podemos configurar o mock para responder de uma determinada forma.
Um framework muito conhecido do mundo Java é um Mockito, futuramente utilizarem ele.
https://site.mockito.org/

Vamos testar?

Usaremos o seguinte método nos testes, ele tem como responsabilidade validar se um número de ISBN é valido, caso não, o método lançará uma exceção.

public void validate(final String value) {
var isbn = Optional.ofNullable(value)
.map(v -> v.replace("-", ""))
.orElseThrow(() -> new IllegalArgumentException("ISBN is invalid"));
if (isbn.length() != 13) {
throw new IllegalArgumentException("ISBN must have 13 characters");
}
if (!StringUtils.isNumeric(isbn)) {
throw new IllegalArgumentException("ISBN must be a number");
}
int sum = 0;
for (int i = 0; i < isbn.length() - 1; i++) {
var multiplier = i % 2 == 0 ? 1 : 3;
sum += Character.getNumericValue(isbn.charAt(i)) * multiplier;
}
var digit = (sum + Character.getNumericValue(isbn.charAt(isbn.length() - 1))) % 10;if (digit != 0) {
throw new IllegalArgumentException("ISBN invalid");
}
}

Podemos começar com um teste onde temos um ISBN válido

@Test
void shouldCreateAObjectIsbnWithSuccess() {
var value = "978-0-306-40615-7";

var isbn = Isbn.from(value);

assertThat(isbn).isNotNull();
assertThat(isbn.getValue()).isEqualTo("978-0-306-40615-7");
}

Vamos entender cada parte do teste.

Primeiro é importante que o titulo ou nome do teste descreva brevemente o que será testado, o cenário e o que esperamos receber do método testado.

void shouldCreateAObjectIsbnWithSuccess () {

depois definimos a entrada:

var value = "978-0-306-40615-7";

na sequencia invocamos o método testado passando a entrada.

var isbn = Isbn.from(value);

por fim, fazemos as validações ou os asserts na saída esperada

assertThat(isbn).isNotNull();
assertThat(isbn.getValue()).isEqualTo("978-0-306-40615-7");

podemos utilizar varias validações, mas é sempre importante lembrar que os testes unitários são testes em pequenas partes do sistemas, parte especificas e por isso devemos focar também nas validações.
Caso seja necessário crie mais testes.

E como sabemos que o teste passou com sucesso? No caso acima o método não lançou nenhuma exceção e todos os assert são verdade. Com isso temos um teste executado com sucesso.

Pronto método testado vamos para o próximo? Não, espera.

Nos testes é importante consideramos as linhas cobertas pelos testes ou o coverage do seu método testado, no caso acima, testamos apenas o caminho feliz ou o caso de sucesso mas e os casos de falha? Para atingirmos uma cobertura alta precisamos testar os casos de falha também, assim temos uma garantia maior que nossa validação de ISBN é realmente boa.

Utilizando o sonarqube verificamos que até o momento estamos com 80% de cobertura.

Para cobrir totalmente o método vamos precisar mais alguns testes

@Test
void shouldReturnIllegalArgumentExceptionWhenTheValueIsNull() {
assertThatThrownBy(() -> Isbn.from(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("ISBN is invalid");
}
@Test
void shouldReturnIllegalArgumentExceptionWhenTheValueHasMoreThan13Characters() {
assertThatThrownBy(() -> Isbn.from("978-0-306-40615-12"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("ISBN must have 13 characters");
}
@Test
void shouldReturnIllegalArgumentExceptionWhenTheValueHasLetters() {
assertThatThrownBy(() -> Isbn.from("978-0-306-4a615-7"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("ISBN must be a number");
}
@Test
void shouldReturnIllegalArgumentExceptionWhenTheValueIsInvalid() {
assertThatThrownBy(() -> Isbn.from("978-0-306-40615-8"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("ISBN invalid");
}

Com isso teremos 100% de cobertura do nosso método e todas as validações testadas, agora sim!

Importante, não é porque nosso método tem 100% de coverage que ele está realmente bem testado, foque nos cenários possíveis de sucesso e falhas e por consequência você chegar em um cover de 100% com qualidade.

No repositório https://github.com/igorcurvelo/my-bookcase

você encontrará mais exemplos de testes unitários.

É isso!

E bons testes!!

--

--