Introdução ao ArchUnit
        No desenvolvimento de software, garantir que a arquitetura do projeto seja respeitada ao longo do tempo é fundamental para manter a qualidade e a facilidade de manutenção do código. Uma ferramenta que tem se destacado nesse aspecto é o ArchUnit, uma biblioteca Java para testar arquiteturas de forma declarativa e fácil. Neste post, vamos explorar como você pode utilizar o ArchUnit para garantir que sua equipe não utilize classes obsoletas como java.util.Date e como manter a integridade de camadas em projetos Spring.
Configurando o ArchUnit
Antes de começarmos com os exemplos de testes, você precisará adicionar o ArchUnit ao seu projeto. Aqui está como você pode fazer isso usando Maven e Gradle:
Maven
<dependency>
    <groupId>com.tngtech.archunit</groupId>
    <artifactId>archunit</artifactId>
    <version>1.3.0</version>
</dependency>
Gradle
testImplementation 'com.tngtech.archunit:archunit:1.3.0'
Essas dependências adicionam o ArchUnit apenas ao escopo de testes do seu projeto, o que é adequado, já que o ArchUnit é utilizado principalmente para escrever testes de arquitetura.
Evitando o Uso de java.util.Date
A classe java.util.Date é considerada obsoleta em muitos casos, sendo recomendado o uso das classes do pacote java.time, como LocalDate. Com o ArchUnit, podemos criar testes para garantir que ninguém no projeto está utilizando java.util.Date. Veja um exemplo de como fazer isso:
package io.github.gasparbarancelli.blog;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.lang.ArchRule;
import org.junit.jupiter.api.Test;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
public class JavaUtilDataArchitectureTests {
    @Test
    public void noJavaUtilDateUsage() {
        JavaClasses importedClasses = new ClassFileImporter().importPackages("io.github.gasparbarancelli.blog");
        ArchRule rule = noClasses()
            .should().dependOnClassesThat()
            .resideInAPackage("java.util")
            .andShould().haveSimpleName("Date");
        rule.check(importedClasses);
    }
}
Este teste irá falhar se qualquer classe no pacote especificado fizer referência direta à classe java.util.Date.
Validando Camadas em Projetos Spring
Projetos Spring comumente utilizam uma divisão clara de responsabilidades entre Controllers, Services e layers de Repositories. Com o ArchUnit, você pode definir regras para garantir que essa estrutura seja respeitada. Veja como você pode fazer isso:
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.lang.ArchRule;
import static com.tngtech.archunit.library.Architectures.layeredArchitecture;
public class SpringLayerArchitectureTests {
    @Test
    public void validateLayerDependencies() {
        JavaClasses importedClasses = new ClassFileImporter().importPackages("io.github.gasparbarancelli.blog");
        ArchRule rule = layeredArchitecture()
            .consideringAllDependencies()
            .layer("Controller").definedBy("..controller..")
            .layer("Service").definedBy("..service..")
            .layer("Repository").definedBy("..repositories..")
            .whereLayer("Controller").mayNotBeAccessedByAnyLayer()
            .whereLayer("Service").mayOnlyBeAccessedByLayers("Controller")
            .whereLayer("Repository").mayOnlyBeAccessedByLayers("Service");
        rule.check(importedClasses);
    }
}
Este teste assegura que cada camada só seja acessada por camadas superiores permitidas, mantendo assim a estrutura desejada e evitando acoplamentos indesejados.
Conclusão
O uso do ArchUnit para testar e validar a arquitetura de seu software pode ser uma ferramenta poderosa para manter a consistência e a qualidade do código ao longo do desenvolvimento. Com testes claros e objetivos, é possível evitar regressões arquiteturais e garantir que boas práticas sejam seguidas por todos os desenvolvedores da equipe.